Reputation: 20658
Assume I have a Tag
table (Id int
and Name nvarchar(100)
) with 3 values:
1 Software
2 Hardware
3 Warehouse
Now I want to query with keyword, and prioritize the ones that starts with the keyword over the containing one. So at first I write this query:
SELECT 0 AS SortCol, *
FROM Tag T
WHERE CHARINDEX(@keyword, T.Name) = 1
UNION
SELECT 1 AS SortCol, *
FROM Tag T
WHERE T.Name LIKE ('%' + @keyword + '%')
ORDER BY SortCol, Name;
However that did not work because the SortCol
column no longer make them distinct (the Warehouse
value appears twice because it is correct in both).
That's when I think I need to manually call DISTINCT
by getting rid of that column:
SELECT DISTINCT T2.Id, T2.Name
FROM
(SELECT 0 AS SortCol, *
FROM Tag T
WHERE CHARINDEX(@keyword, T.Name) = 1
UNION
SELECT 1 AS SortCol, *
FROM Tag T
WHERE T.Name LIKE ('%' + @keyword + '%')
ORDER BY SortCol, T.Name) AS T2;
However, this does not work because I get this error:
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified.
What am I missing here? How can I use UNION
with ORDER BY
in both statements?
Upvotes: 1
Views: 116
Reputation: 222442
Just put a CASE in the ORDER BY clause directly, like :
SELECT
*
FROM Tag
WHERE name like ( '%' + @keyword + '%' )
ORDER BY
CASE
WHEN CHARINDEX(@keyword, T.Name) = 1 THEN 0
ELSE 1
END,
names
Upvotes: 0
Reputation: 175646
If for some reason you need this SortCol
column it is possible:
DECLARE @keyword NVARCHAR(MAX) = N'ware';
WITH cte AS (
SELECT *, ROW_NUMBER() OVER(PARTITION BY Name ORDER BY Name) rn
FROM (
SELECT 0 AS SortCol, *
FROM Tag T
WHERE CHARINDEX(@keyword, T.Name) = 1
UNION
SELECT 1 AS SortCol, *
FROM Tag T
WHERE T.Name LIKE ('%' + @keyword + '%')) s
)
SELECT SortCol, Id, name
FROM cte
WHERE rn = 1
ORDER BY SortCol, Name;
Upvotes: 1
Reputation: 453142
You don't need the UNION
you can use
SELECT *
FROM Tag T
WHERE T.Name LIKE '%' + @keyword + '%'
ORDER BY CASE WHEN T.Name LIKE @keyword + '%' THEN 0 ELSE 1 END,
Name;
Upvotes: 5