CASE expression when with multiple column order - sql

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.

Related

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

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

SQL Server Sorting Int Column bug

I have this SQL statement that sorts the rows depending on their change_order and change_id.
My statement looks like this:
select *
from change_dtl_from2
where chnfr_hdrno = 'CH000009'
order by
case
when chnorder is null
then 1
else 0
end asc, change_id asc
Where chnfr_hdrno is the document number, chnorder is change_order, change_id is unique key per row.
If I execute that statement, the result will be like this:
As you can see, the row with chnorder value of 5 is on the top most where the chnorder is set its order by ascending. I don't know where or what I'm doing wrong.
The default value of chnorder is null and is an int column. That's why I'm confused because whenever I add a new row, the new one will be on top most. I hope you can all help me. :)
SQL does everything correct depending on your query. With your CASE-Statement you "replace" all non-NULL-values to 1 and sort them only by change_id. If you only want to replace NULL by 1 you should use
order by (case when chnorder is null then 1 else chnordner end) asc
or you should use
order by (case when chnorder is null then 1 else 0 end) asc, chnordner asc, change_id asc

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

0 come last when sorting ascending

I am trying to select from one table a list of products ordered by price, year, name, and others....
The problem is that I must make zero values come last when sorting ascending.
My code is:
SELECT * FROM Product P
ORDER BY CASE WHEN #OrderBy='Date ASC' THEN Date END ASC,
CASE WHEN #OrderBy='Price ASC' THEN Price END ASC,
CASE WHEN #OrderBy='Title ASC' THEN Title END ASC,
CASE WHEN #OrderBy='' THEN Match END
This works but don't put the zero at the bottom of the list.
So, I tried to transform it (see next code), but it gave me the error Incorrect syntax near ','.
SELECT * FROM Product P
ORDER BY CASE WHEN #OrderBy='Price ASC' THEN
(case A.Price WHEN 0 THEN 1 ELSE 0 END,A.Price )
END ASC
I appreciate any help
You can do it by testing for price-ordering twice:
SELECT * FROM Product P
ORDER BY CASE WHEN #OrderBy='Date ASC' THEN Date END ASC,
CASE WHEN #OrderBy='Price ASC' THEN CASE WHEN Price = 0 THEN 1 ELSE 0 END ASC,
CASE WHEN #OrderBy='Price ASC' THEN Price END ASC,
CASE WHEN #OrderBy='Title ASC' THEN Title END ASC,
CASE WHEN #OrderBy='' THEN Match END
By the way, the implicit value of the case expression when #orderBy doesn't equal the string is null. When the sort column contains all nulls, it effectively disables sorting for that attribute.
I would suggest using a large dummy price:
ORDER BY CASE WHEN #OrderBy='Price ASC' THEN 99999999 ELSE A.Price END ASC
or if you DBMS supports NULLS LAST:
ORDER BY CASE WHEN #OrderBy='Price ASC' THEN NULLIF(A.Price,0) END ASC NULLS LAST
You can try with this syntax:
SELECT *,
CASE WHEN #OrderBy = 'Price ASC' AND Price = 0 THEN 1 ELSE 0 END AS OrderPriceZeroLast
FROM Product P
ORDER BY OrderPriceZeroLast,
CASE WHEN #OrderBy = 'Date ASC' THEN Date END ASC,
CASE WHEN #OrderBy = 'Price ASC' THEN Price END ASC,
CASE WHEN #OrderBy = 'Title ASC' THEN Title END ASC,
CASE WHEN #OrderBy = '' THEN Match END
I can't add comments yet. There is bug in your code
SELECT * FROM Product P
ORDER BY CASE WHEN #OrderBy='Price ASC' THEN
(case A.Price WHEN 0 THEN 1 ELSE 0 END,A.Price )
END ASC
Shoud be smth like
SELECT *
FROM Product P
ORDER BY
CASE
WHEN #OrderBy='Price ASC'
THEN
CASE A.Price
WHEN 0
THEN 1
ELSE 0
END
END,
A.Price
This may seem like a hack but you could create a new column on the result set on the fly. Like this:
SELECT *, [name of column that may contain zeroes] as foo WHERE /* rest of your code */
Then you could sort DESC on foo and ASC on the rest. Just remember to now show foo to the user. Also notice that yes, you'll get the same column in the result set twice. You also have to use a CASE to turn all non-zero values into 1 (or some other constant value).
Try this to sort 0 value to last, when there are 0,1,2,... values are in field.
It will bring 1, 2 ,... and 0 to last order.
select * from Product
order by
case
when OrderBy = 0
then -1
else 0
end,
OrderBy desc
-Chirag

Quick SQL question for sorting

I have this ordering sql at the end of my sql statement:
ORDER BY CASE WHEN LOWER(LEFT(E.name, 1)) BETWEEN 'a' AND 'z'
THEN 0 ELSE 1 END, E.name ASC
that orders the result this way: names starting with letters first and numbers later.
How can I add this: at first, names with a preference set on true, then all what I already have. ie: E.preference='true' will goes on the top.
Can't you just add the preference sort before your existing sort?
ORDER BY Case When e.Preference = 'true' then 0 else 1 end,
CASE WHEN LOWER(LEFT(E.name, 1)) BETWEEN \'a\' AND \'z\' THEN 0 ELSE 1 END, E.name ASC
Edit
Or if you want to have all preference = true first in any order then sort using your existing method then I think you could use:
Order By Case When e.Preference = 'true' Then 0
Else
CASE
WHEN LOWER(LEFT(E.name, 1)) BETWEEN \'a\' AND \'z\' THEN 1
ELSE 2 END
End, e.name asc
Edit 2
Taking this one step further you can have all preference = true first then sort these using your current method, then sort all the preference=false
Order By Case When e.Preference = 'true' Then
CASE
WHEN LOWER(LEFT(E.name, 1)) BETWEEN \'a\' AND \'z\' THEN 0
ELSE 1 END
Else
CASE
WHEN LOWER(LEFT(E.name, 1)) BETWEEN \'a\' AND \'z\' THEN 2
ELSE 3 END
End, e.name asc
I'm not sure how this would affect the performance of the query though.
You can list multiple ORDER BY columns. So you could do ORDER BY e.preference, CASE WHEN LOWER(LEFT(E.name, 1)) BETWEEN \'a\' AND \'z\' THEN 0 ELSE 1 END, E.name ASC and if your non-preferred rows had NULL as preference then you'll get all preferred first (ordered by your existing criteria within that group) then all non-preferred (ordered by your existing criteria within that group)