ORDER BY CASE WHEN ... ELSE ... END in PostgreSQL - sql

I have my ORDER BY clause as following:
...
ORDER BY CASE WHEN boolean_column is true THEN text_column END ASC,
CASE WHEN boolean_column is false THEN text_column END DESC
Is it somehow possible to replace the second CASE in an ELSE? It feels odd to have two conditions instead of a regular if else/when else as you normally would do.

You can use this trick to shorten the logic:
ORDER BY (CASE WHEN boolean_column THEN text_column END) ASC,
text_column DESC
It is still two order by keys though.

If the type of text_column is numeric. you can try this.
ORDER BY CASE WHEN boolean_column is true THEN text_column
ELSE -1 * text_column END ASC

You can do the sorting at first, getting the position of each record, and then choose the sorting direction
WITH rows_with_positions AS (
SELECT
boolean_column,
text_column,
ROW_NUMBER() OVER (ORDER BY text_column) AS position,
..
FROM your_table
)
SELECT text_column, ..
FROM rows_with_positions
ORDER BY
CASE WHEN boolean_column
THEN position
ELSE -1 * position
END
ASC

Related

What happens when I pass an CASE expression to the LAST_VALUE function

My LAST_VALUE function looks somethin like this
LAST_VALUE(
CASE
WHEN statement_1 then 0
WHEN statement_2 then 1
WHEN statement_3 then 0
ELSE NULL
END IGNORE NULLS) OVER (PARTITION BY column1 ORDER BY column2)
Can someone explains what value is the LAST_VALUE supposed to return if there is expression.
I understand what happens when a column is passed, but incase of such expressions no clue whatsoever.
You can find the description and examples at https://docs.oracle.com/cd/E11882_01/server.112/e41084/functions085.htm#SQLRF00655
Regards...
Btw. the CASE ... END structure is just as you are selecting values from the table field but with If condition. It doesn't affect the LAST_VALUE function.
It is something like this:
CASE WHEN ID = 1 THEN 10 WHEN ID = 2 THEN 20 ELSE 99 END
where ID = 1 is Statement1, ID = 2 is Statement2 ... and so on..
The same as if your case expression were itself a column...
SELECT
*,
LAST_VALUE(new_column IGNORE NULLS)
OVER (PARTITION BY column1
ORDER BY column2
)
FROM
(
SELECT
*,
CASE
WHEN statement_1 then 0
WHEN statement_2 then 1
WHEN statement_3 then 0
ELSE NULL
END
AS new_column
FROM
your_table
)
sub_query

CASE expression when with multiple column order

Posted value if 0 then, make the order according to these columns: isl_tar, isl_saat, ref_kod, isl_ref, kayit_no
Posted value if 1 then make the order according to this column: tutar
This script is not working:
I want to sort by the second case
select t.*
from TEMP_HESAP_HAREKET t
order by case 1
when 0 then
TO_NUMBER(TO_CHAR(ISL_TAR, 'YYYYMMDD') ||
SUBSTR(ISL_SAAT, 1, 2) || SUBSTR(ISL_SAAT, 4, 2))
end asc,
REF_KOD asc,
ISL_REF asc,
KAYIT_NO asc,
case 1
when 1 then
tutar end
You seem to want:
order by (case 1 when 1 then tutar end), -- handle that case first
TO_NUMBER(TO_CHAR(ISL_TAR, 'YYYYMMDD') ||
SUBSTR(ISL_SAAT, 1, 2) || SUBSTR(ISL_SAAT, 4, 2))
REF_KOD asc,
ISL_REF asc,
KAYIT_NO asc
I assume the expression on isl_tar is correct. It seems like a simple column reference would suffice.
I assume the value after the CASE gets put there somehow, maybe by some application which fires the statement.
Then you could order by five CASE.
If the value is 0 then return the respective column from your list of columns you want to sort in case of a 0.
In the first CASE return tutar if the value is 1. In all the other CASE, if the value is 1, return always the same value or none at all (NULL) which will be the default anyway, if you don't have a WHEN for it in there at all.
ORDER BY CASE ?
WHEN 0 THEN
ISL_TAR
WHEN 1 THEN
TUTAR
END ASC,
CASE ?
WHEN 0 THEN
ISL_SAAT
END ASC,
CASE ?
WHEN 0 THEN
REF_KOD
END ASC,
CASE ?
WHEN 0 THEN
ISL_REF
END ASC,
CASE ?
WHEN 0 THEN
KAYIT_NO
END ASC
The ? have to be replaced with the 0 or 1.
However, if there is an application placing the values after the CASE, it might be a "cleaner" (easier to read, understand and maintain) way to make it change the complete ORDER BY expression instead of putting the 0 or 1.

SQL: Order first by table.column = 'matchingstring', then order everything else alphabetically?

I'm currently using MySQL and I want to order my book_versions records where the book_versions.name = 'paperback' show up first, and then the rest of the book_versions (book_versions.name != 'paperback') show. How would I accomplish this?
order by case when book_versions.name = 'paperback' then 0 else 1 end,
book_versions.name, -- remove this line if other names should not be ordered
book_versions.isbn
See sqlFiddle to see the difference
in mysql, you can also use field
order by field(book_versions.name, 'paperback') DESC,
book_versions.name ASC,
book_versions.isbn ASC
Try:
ORDER BY
CASE WHEN book_versions.name = 'paperback' THEN 0 ELSE 1 END, -- puts paperbacks first (because paperbacks cause this to =0, which is ordered before 1)
book_versions.name -- then order alphabetically

Null value in order by clause

I have a weird scenario, in which I need to keep all the rows at top in which X column has NULL value else sort by Y column. Can you help me in writing query.
ORDER BY CASE WHEN X IS NULL THEN 0 ELSE 1 END, Y
You can use a CASE statement in ORDER BY:
ORDER BY
CASE WHEN X IS NULL THEN 0 ELSE 1 END ASC, Y
Here you go, this will work with any sql platform -- for a specific platform there might be a better way to do it.
SELECT * FROM
(
SELECT 1 AS orderC, *
FROM tableName
WHERE Xcolumn is null
UNION ALL
SELECT 2 AS orderC, *
FROM tableName
WHERE Xcolumn is not null
)
ORDER BY orderC ASC, columnY
Note, if you don't want orderC to be in the output, just specify all the other columns in the outer select.
Sharing what I learned before using:
ORDER BY FIELD(Xcolumn, NULL) DESC, Ycolumn DESC
SELECT * FROM TABLENAME ORDER BY X ,Y
You can use query like below:
SELECT * FROM Emp WHERE empId= 6 AND DELETED = 0
ORDER BY CASE WHEN DOB IS NULL THEN 0 ELSE 1 END
, CREATETIMESTAMP.
for more details you can see here

Order By a field being equal to a specific value?

Let's say I have this MySQL query:
SELECT * FROM A WHERE x='abc' OR y=0;
How can I prioritize the rows so that cases where x='abc' are ordered FIRST? If y=0 but x!='abc', I want those rows to come after cases where x='abc'.
Can this be accomplished with a simple ORDER BY clause?
Thanks!
SELECT *
FROM A
WHERE x='abc'
OR y=0
order by case when x='abc' then 0 else 1 end;
I would do it with a case statement:
SELECT *,
CASE WHEN column_one = 0 THEN 0
WHEN column_two = 'ADMIN' THEN 1
END AS multi_column
FROM sometable
ORDER BY multi_column;
ORDER BY FIELD(x,'abc',x)