Reputation:
I was reading an sql book, one of questions is:
Write a query against the Sales.Customers table that returns for each customer the customer ID and region. Sort the rows in the output by region, having NULL marks sort last (after non-NULL values).Note that the default sort behavior for NULL marks in T-SQL is to sort first (before non-NULL values).
And the answer is :
SELECT custid, region
FROM Sales.Customers
ORDER BY
CASE WHEN region IS NULL THEN 1 ELSE 0 END, region;
I can kind of get the idea but still confused, let's take the record with custid = 9 for instance: since custid 9 has a null region, in the case cstatement return 1, so the query is sth like:
ORDER BY 1, region
which is equivalent to:
ORDER BY custid, region --because custid is the first column
so how come the custid 9 is not before custid 10(the second record in the output)? isn't that output needs to order by custid first, so 9 is before 10?
Upvotes: 1
Views: 657
Reputation: 37472
ORDER BY CASE
WHEN region IS NULL THEN
1
ELSE
0
END,
region
is not equivalent to
ORDER BY 1,
region
because in the second one the first column to sort by is always constant, whereas in the first it can change depending on the CASE
.
And
ORDER BY 1,
region
is also not equivalent to
ORDER BY custid,
region
again in the first the 1
is constant but custid
is variable.
What
ORDER BY CASE
WHEN region IS NULL THEN
1
ELSE
0
END,
region
does is to "generate" a new column to sort by depending on the content of region
. That new column gets 1
when region
is null 0
otherwise. If you imagine this new column in the table it would look like
custid | region | new column
...
10 | BC | 0
...
9 | NULL | 1
...
Now if this gets sorted by the new column and the region the customer with ID 10
comes before the customer with ID 9
because the one with ID 10
has the lower value for the new column -- 0
against the 1
from the customer with the ID 9
.
Upvotes: 1
Reputation: 91
The idea is to use CASE statement to create a calculate virtual column to mark the nulls as 0 and none nulls as 1 and then sort accordingly.
if you use 0 in the order by clause you will get an error because you don't have a column at position of 0, also if you reorder the selected columns the result will be the same. so the output of case statement is not a position of column it's a calculated column.
customer_id region marker
not important if null 0
Upvotes: 0
Reputation: 272086
so the query is sth like
ORDER BY 1, region
No this is incorrect. The expression CASE WHEN region IS NULL THEN 1 ELSE 0 END
is evaluated per-row; and the 1
is a value instead of column position. Column position inside ORDER BY
can only specified only as a literal and not as an expression. So this:
custid region
8 NULL
9 NULL
10 BC
42 BC
45 CA
Becomes:
custid region case...
8 NULL 1
9 NULL 1
10 BC 0
42 BC 0
45 CA 0
And the sorted results could be:
custid region case...
10 BC 0
42 BC 0
45 CA 0
8 NULL 1
9 NULL 1
Or:
custid region case...
42 BC 0
10 BC 0
45 CA 0
9 NULL 1
8 NULL 1
Upvotes: 0
Reputation: 1269603
Your interpretation is incorrect. The 1
is simple a number, not a column reference.
The query is equivalent to:
SELECT custid, region
FROM (SELECT c.*,
(CASE WHEN region IS NULL THEN 1 ELSE 0 END) as region_is_null
FROM Sales.Customers c
) c
ORDER BY region_is_null, region;
This is an important distinction about numbers in the ORDER BY
. The expression:
ORDER BY 1
refers to the first column. However,
ORDER BY 1 + 0
is simply a numeric expression that returns the constant 1
-- and will result in an error in SQL Server (which does not allow constants in ORDER BY
).
Upvotes: 2
Reputation: 37473
You can try below - in your case 0 will be comign first then 1 so you need to change the order of the value, or you can do desc order if you don't want to change the value
SELECT custid, region
FROM Sales.Customers
ORDER BY
CASE WHEN region IS NULL THEN 0 ELSE 1 END, region
Upvotes: 0