Quick SQL question for sorting - sql

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)

Related

SQL Query, ELSE LAG argument to pull value above in same row

I am hoping someone will be able to help I have the below query (Query1) that works fine. but I want to change the line
CASE WHEN pegging_level_no = 0 THEN (supply_order_num) ELSE 'TEST' end AS Assembly_WO
So that rather than returning 'TEST' if pegging_level_no = 0 it returns the Value from the row above in this new column, I am not sure this is possible? (I am new to SQL, and learning as I go)
Basically, I am trying to recreate the formula if it was in excel similar to =IF(D2=0,O2,AF1) this would be in cell AF2.
I have tried using the LAG Function but can not get it to work below is what I have been trying to use but does not work, tried adding a group by but struggling!
CASE WHEN pegging_level_no = 0 THEN (supply_order_num) ELSE LAG(Assembly_WO) OVER(PARTITION BY pegging_level_no) END AS Assembly_WO
Query1
SELECT
plant_sys,
so_tran_order_number,
so_tran_line_number,
pegging_level_no,
demand_order_number,
supply_type_desc,
supply_material,
allocated_qty,
ext_cost,
pegging_seq_2,
Sum(allocated_qty)OVER (partition BY plant_sys, supply_material) AS Total_Qty,
CASE WHEN est_cost <> 0 and supply_type_desc ='Production order - PO' THEN (est_cost/allocated_qty)end AS WoPO_cost_Ea,
-- CASE WHEN pegging_level_no = 0 THEN (supply_order_num) ELSE LAG(Assembly_WO) OVER(PARTITION BY pegging_level_no) END AS Assembly_WO
CASE WHEN pegging_level_no = 0 THEN (supply_order_num) ELSE 'TEST' end AS Assembly_WO
FROM
og_surf_snop_dm.sop_plan_calc_cp_t
WHERE PRODUCT_COMPANY = 'OFS' AND PLANT_SYS = '0003'
ORDER BY
pegging_seq_2 ASC,
pegging_level_no ASC;
Sample Data(so where it says 'TEST' in the last column I would like it to return the value from the cell above in column heading 'ASSEMBLY_WO:

SQL - Subselect in select clause - how to create column which decides uniqity logic

I am trying to write subselect which will run through returned data, then checks status of all and then decides uniquity logic.
Is there any way to find out following ?
case any of data has 'Active' status first one will be marked as 1 everything else as 0
case there is no 'Active' status then first 'Expired' status will by marked as 1 and everything else as 0
case there is no 'Active' and 'Expired' status then first 'In Progress' will be marked as 1 and everything else as 0
I was trying to write it like this but i need to have it in one case statement
SELECT a.id, a.status,
,(SELECT
CASE WHEN b.STATUS = 'Active' THEN 1 ELSE 0 END
CASE WHEN b.STATUS = 'Expired' THEN 1 ELSE 0 END
FROM b.TABLE
WHERE a.id=b.id )AS unique
FROM my.TABLE
Result should look like https://i.stack.imgur.com/qCA74.png picture for expired case
Thank you in advance for any tips.
Use a window function:
select t.*,
(case when row_number() over (partition by id
order by case status when 'Active' then 1 when 'Expired' then 2 else 3 end
) = 1
then 1 else 0
end) as unique_flag
from my.table t;
If the lookup table is the same as source table, then you can use LAG function with constant and use its default value to mark the first row with 1 and others with 0. But you need to order your rows by some fields to deal with duplicates on status.
select a.id, a.status,
lag(0, 1, 1) over(
partition by a.id
order by
case a.status
when 'Active' then 0
when 'Expired' then 1
else 3
end asc,
a.some_more_columns asc /*To find that first row when there are duplicates by status*/
) as unique_flag
from MY_TABLE a
And what about object naming: never use keywords as identifiers. Calling column with date as date, table with users as users and some unknown table as table makes you design error prone.

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 By blanks at bottom when the main order by is a Case statement?

I'd like to ORDER BY listing items that are blanks at the bottom of the result, however the main order by is a case statement.
So, my main Order By clause is this:
ORDER BY CASE WHEN pub = 1 THEN title ELSE t.othertitle END;
To that, I'd like to apply the following CASE so that blanks go to the bottom:
ORDER BY CASE WHEN (above case) = '' THEN 1 ELSE 0 END
Problem is I cannot embed CASE statements.
How would this be done?
Thanks!
You didn't specify your DBMS, so this is ANSI SQL:
ORDER BY nullif(CASE WHEN pub = 1 THEN title ELSE t.othertitle END, '') NULLS LAST
You can in fact embed case statements
ORDER BY CASE COALESCE(CASE pub WHEN 1 THEN title ELSE t.othertitle END, '') WHEN '' THEN 1 ELSE 0 END
You can do this explicitly:
ORDER BY (CASE WHEN pub = 1 AND title = '' THEN 1
WHEN pub <> 1 AND t.othertitle = '' THEN 1
ELSE 2
END) DESC,
(CASE WHEN pub = 1 THEN title ELSE t.othertitle END)
Case statements can only(?) be included in Order by when structuring it to return an INT. Create any kind of ordering logic you'd like but make sure it returns an INT in ascending order:
order by
(case when pub = 1 then 1
when pub is null or pub = '' then 2
else 3 end)

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