Is there a possibility to order the result by an ORDER clause that contains an expression, something like
SELECT colX0 FROM tbp_name ORDER BY (colX1 IS NOT NULL)
or also a more complex expression ?
UPDATE:
In the meanwhile I have found a possibility to solve the above problem:
ORDER BY (case WHEN colX1 IS NULL THEN 1 ELSE 0 END ) ASC
however the question remains, if there is a possibility to order direct by an expression.
No, SQL Server does not support direct conversion of an expression to true/false.
IMHO, one reason is the 3-valued logic. This has 3 outcomes, not 2, of either column is NULL. The NULL is first in SQL generally, always Server but can be specified last in other RDBMS.
ORDER BY (colX1 = colX2)
Using CASE mitigates this and removes ambiguity
ORDER BY
CASE
WHEN colX1 = colX2 THEN 1
WHEN colX1 <> colX2 THEN 2
ELSE 3 NULL case
END
You have to use CASE as per your update, as well ensuring datatypes match (or at least implicitly convertable) in WHEN clauses.
you can use
ORDER BY CASE WHEN condition= 1 THEN 1 ELSE 2 END
you can order by the ordinal position of the column, if you want to SEE the data that you're sorting by... for example, if you want to order by the 1st column, just say 'ORDER BY 1'. Here is an example where I add an expression in the select clause.. and then I order by it in the order by clause
SELECT colX0,
(case WHEN colX1 IS NULL THEN 1 ELSE 0 END )
FROM tbp_name
ORDER BY 2
You'd need to put it in your select first
SELECT
colX0,
CASE WHEN colX1 IS NOT NULL THEN 0 ELSE 1 END AS [COMPUTED1]
FROM tbp_name
ORDER BY COMPUTED1
It's something like that anyway off the top of my head.
http://www.tizag.com/sqlTutorial/sqlcase.php
Related
case when prefinallist.truckbooked is null then 'Immediate' else CAST(prefinallist.previous_date as varchar) END as ETA
The list contain either the word Immediate or datetime.
How to show immediate on the top and date in acending.
You can try to use ORDER BY like this:
ORDER BY (`ETA` = 'Immediate') ASC
or you can also use CASE statement inside the ORDER BY like
ORDER BY CASE WHEN ETA = 'Immediate' THEN 1 ELSE 2 END
As part of some dynamic SQL (ick), I've implemented the 'sort NULLs last' solution described here: Sorting null-data last in database query
ORDER BY CASE column WHEN NULL THEN 1 ELSE 0 END, column
My question is: On non-nullable columns that have ISNULL() applied to them, will the query optimizer strip this out when it realises that it will never apply?
It's not clear why your question mentions the ISNULL function when that isn't in your code.
ORDER BY CASE column WHEN NULL THEN 1 ELSE 0 END, column
First of all this code doesn't work, it is equivalent to CASE WHEN column = NULL which is not what you need.
It would need to be
ORDER BY CASE WHEN column IS NULL THEN 1 ELSE 0 END, column
The optimisation question is easy to test.
CREATE TABLE #T
(
X INT NOT NULL PRIMARY KEY
)
SELECT *
FROM #T
ORDER BY X
SELECT *
FROM #T
ORDER BY CASE WHEN X IS NULL THEN 1 ELSE 0 END, X
DROP TABLE #T
The plan shows a sort operation in the second plan indicating that this was not optimised out as you hoped and the pattern is less efficient than ORDER BY X.
What could be wrong with this query:
SELECT
SUM(CASE
WHEN (SELECT TOP 1 ISNULL(StartDate,'01-01-1900')
FROM TestingTable
ORDER BY StartDate Asc) <> '01-01-1900' THEN 1 ELSE 0 END) AS Testingvalue.
The get the error:
Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
As koppinjo stated what your current (broken) query is doing is checking if you have a NULL-value (or StartDate = '01-01-1900') in your table, return either a 1 or a 0 depending on which, and then attempting to SUM that single value.
There are 2 different logical things you want.
Either getting the amount of rows that has a StartDate or checking if any row is missing StartDate.
SELECT --Checking if there is a NULL-value in table
(
CASE WHEN
(SELECT TOP 1 ISNULL(StartDate,'01-01-1900')
FROM TestingTable
ORDER BY StartDate Asc) <> '01-01-1900' THEN 1
ELSE 0
END
) AS TestingValue
SELECT SUM(TestingValue) TestingValue --Give the count of how many non-NULLs there is
FROM
(
SELECT
CASE WHEN
ISNULL(StartDate,'01-01-1900') <> '01-01-1900' THEN 1
ELSE 0
END AS TestingValue
FROM TestingTable
) T
Here is a SQL Fiddle showing both outputs side by side.
Hard to say, but you probably want something like this:
SELECT
SUM(TestingValue)
FROM
(SELECT
CASE
WHEN ISNULL(StartDate,'01-01-1900') <> '01-01-1900'
THEN 1
ELSE 0
END AS TestingValue
FROM TestingTable) t
As your original query is written now, your subquery will return 1 value overall, so your sum would be 1 or 0 always, not to mention it is illegal. To get around that, this SQL will apply the case statement to every row in the TestingTable and insert the result into a derived table (t), then the 'outer' select will sum the results. Hope this helps!
Is there any difference between writing :
select
...,
mySum= CASE
WHEN i IS NULL THEN 0 ELSE SUM(i)
END
...
vs
select
...,
mySum= SUM( CASE WHEN i IS NULL THEN 0 ELSE i
END
)
...
Or is it just 100% the same ( logically and traps...)?
On my test data, I get the same results returned, and near identical execution plans:
All the same costs, just two operations reversed.
I think logically there is no difference. But I think you don't need to check for null in this case as aggregate functions ignore nulls
BTW, You can simplify case with a isnull as follows. (Edit: mistakenly added sum(isnull(i,0)) changed to Isnull(sum(i),0))
select Col1, Isnull(sum(i),0) as mySum
from yourTable
group by Col1
My question is similar to this one: How to display a table order by code (like 01, 02… then null columns)?, but for SQL Server.
In short, I have a SELECT statement, that returns the following:
ColumnA ColumnB
X NULL
Y 1
Z 2
..where the ordering is done by ColumnB.
How can we force the (columnB = NULL) type of rows to the bottom? ie, the expected result is this:
ColumnA ColumnB
Y 1
Z 2
X NULL
Thank you SOF community.
...or in order to avoid value clashing...
SELECT
ColumnA,
ColumnB
FROM YourTable
ORDER BY
CASE WHEN ColumnB IS NULL THEN 1 ELSE 0 END ASC,
ColumnB
You can also use isnull:
select * from thetable order by isnull(columnb, 99999)
isnull will replace null with the value you provide to it, so in this case, if the column is null, it will replace it with 99999. You can set the value to some big number so it will be at the bottom of the order.
hoping to help someone,
I just wanted to add that I have had a similiar issue, using row_number and partition by -
when it is zero put it at the end sort of thing
and I used the script below (partial view):
,T.MONTHS_TO_AUTOGROWTH
,the_closest_event=ROW_NUMBER() OVER (PARTITION BY SERVERID, DRIVE ORDER BY
CASE WHEN MONTHS_TO_AUTOGROWTH > 0 THEN MONTHS_TO_AUTOGROWTH ELSE 9999
END )
the result is ordered by MONTHS_TO_AUTOGROWTH but zero comes last