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
Related
I was able to remove the duplicate rows, but I would like to remove the duplicate rows based on one more constraint. I want to keep only a row with a smaller number of NULL values.
Original Table
Ran the SQL Server Query
WITH CTE AS(
SELECT *,
RN = ROW_NUMBER()OVER(PARTITION BY Premise_ID ORDER BY Premise_ID)
FROM sde.Premise_Test
)
DELETE FROM CTE WHERE RN > 1
Result:
But I want to get this result
I have modified the SQL script as per the comment from Aaron. but the result is still the same. DB fiddle is showing NULL from IS NULL getting highlighted.
Update the ROW_NUMBER() function like this (no, there is no shorter way):
RN = ROW_NUMBER() OVER (
PARTITION BY Premise_ID
ORDER BY Premise_ID,
CASE WHEN Division IS NULL THEN 1 ELSE 0 END
+ CASE WHEN InstallationType IS NULL THEN 1 ELSE 0 END
+ CASE WHEN OtherColumn IS NULL THEN 1 ELSE 0 END
...
)
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.
I am testing ORDER BY clause with CASE, and came across this problem.
My test select statement:
SELECT to_date as "One", field1 as "Two"
FROM(
SELECT to_date('yyyy-mm-dd', '2017-10-10'), '333' union all
SELECT to_date('yyyy-mm-dd', '2017-09-09'), '111' union all
SELECT to_date('yyyy-mm-dd', '2017-09-09'), '222' union all
SELECT to_date('yyyy-mm-dd', '2017-09-09'), '' union all
SELECT to_date('yyyy-mm-dd', '2017-09-09'), ''
)
ORDER BY One DESC,
CASE when Two = '' then 1
else 0 end DESC
And it's result may vary in a way, that sorting by second column is random:
How should I modify CASE clause to avoid it?
In Oracle, an empty string '' is the identical to NULL so your query is:
ORDER BY
One DESC,
CASE when Two = NULL then 1 else 0 end DESC
When comparing values, the are possible states are:
Equality Result
------------------------ ------
value = value TRUE
value = other_value FALSE
value = NULL NULL
NULL = NULL NULL
Your CASE expression will only evaluate to 1 when the equality evaluates to TRUE and this will never be the result when at least one side of the equality is NULL.
What you want is to use IS NULL rather than = '':
ORDER BY
One DESC,
CASE WHEN Two IS NULL THEN 1 ELSE 0 END DESC,
Two DESC;
Which you can simplify to:
ORDER BY
One DESC,
Two DESC NULLS FIRST;
The default for DESC ordering is NULLS FIRST so you could further simplify it to:
ORDER BY
One DESC,
Two DESC;
However, I would not take it this far as you are better explicitly stating that you are expecting NULL values to be ordered before non-NULL so future developers know that that is your intended ordering (rather than just an unintentional side-effect of your query).
Add the column two as third order condition
ORDER BY One DESC,
CASE when Two = '' then 1 else 0 end DESC,
Two DESC
The second order condition only puts empty entries first and not more.
This needs to be done in Firebird with FlameRobin
my problem is very simple but I stil need help with it
Select * from Clients
order by Case town
when 'amsterdam' Then 1
when 'rotterdam' Then 2
when 'maastricht' Then 3
else 4 end,
Case Gender
when null then 1
when 'Male' then 2
when 'Female' then 3
else 4 end,
---From Here it goes wrong what I want--
Case name
when null then 1
when asc then 2 ( and here I want the names alphabetical descending )
else 3 end
because sql is so limited I need to some help here
I think you are better off building those calculated fields in your select and then working with them for ordering like this:
SELECT *,
(CASE town
WHEN 'amsterdam' THEN 1
WHEN 'rotterdam' THEN 2
WHEN 'maastricht' THEN 3
ELSE 4
END CASE) as town_order,
CASE gender
WHEN ...
...
ELSE 4
END CASE) as gender_order,
CASE gender
WHEN ...
...
ELSE 3
END CASE) as name_order
ORDER BY town_order ASC, gender_order ASC, name_order ASC, name DESC
Of course this would be a VERY non-optimal query, not able to use any sort of indexes for sorting. If you really want to query efficiently, you should add specific town_order, gender_order, etc. fields to your table and place indexes on them.
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