Order by a specific value first then show all rest in order - sql

The below query returns list of areas i want to show the null value which is '--- All ----' then the rest of the values.
So out out will be
AreaID AreaName
Null '--- All ----'
1 area1
2 area2
etc..
Query
SELECT
dbo.Areas.AreaID,
dbo.Areas.AreaName
FROM dbo.Areas
UNION
SELECT
NULL,
'--- All ----'
ORDER BY dbo.Areas.AreaName

Try this:
SELECT AreaID,
AreaName
FROM (
SELECT dbo.Areas.AreaID,
dbo.Areas.AreaName
FROM dbo.Areas
UNION
SELECT NULL,
'--- All ----'
) AS t
ORDER BY CASE
WHEN AreaID IS NULL THEN 1
ELSE 2
END,
AreaName
Note: Using a nested derived table is not required as it would have sufficed to use ORDER BY like you did in your query. I think though it adds to the readability of the query.

One option is to use a CASE expression to place your NULL record first in the result set. You can also add a second ordering condition to sort on the area name after this first condition has been applied.
SELECT
dbo.Areas.AreaID,
dbo.Areas.AreaName
FROM dbo.Areas
UNION
SELECT
NULL,
'--- All ----'
ORDER BY CASE WHEN dbo.Areas.AreaID IS NULL THEN 0 ELSE 1 END,
dbo.Areas.AreaName

Related

how to aggregate and return zero in non exixtent where condition

I have table like follows.
case_no history_no
A22010021 1
A22010021 2
A22010021 3
select
case
when max(history_no) is null
then 0
else max(history_no) end as max
from
table
where
case_no = 'A22010022'
group by
case_no
it returned
max
Null
when I set case_no = 'A22010021' it returned
max
3
My desired result is to get 1 where non-existent case_no is extracted.
max
0
What is the root cause of this?
Are there any ways to achieve this?
Thanks
I think group by clause is not required in your use case.
select coalesce(max(history_no),0)
from table_case_no where case_no='A220100234'
if you want to use group by clause then use below query to fill missing case no to put 0 value.
select case_no,max(history_no) max_history_no
from table_case_no where case_no = 'A22010022' group by case_no
union
--below query for non-existent case no
select 'A22010022' as id,0
where not exists
(
select 1 from table_case_no where case_no='A22010022'
)
;

SQL Query problem (2 different order by) in 1 table

This is the original table:
I have 2 different query and I want to make 1 query for these:
SELECT *
FROM SAMPLE
WHERE ORDER_PRIORITY<40
ORDER BY FS_GENERATE_DATE IS NOT NULL, FS_GENERATE_DATE,ORDER_PRIORITY,CREATE_ID,CR_DATE,ORDER_QTY;
second:
SELECT *
FROM SAMPLE
WHERE ORDER_PRIORITY>=40
ORDER BY FS_GENERATE_DATE IS NOT NULL, FS_GENERATE_DATE,ORDER_PRIORITY,CREATE_ID,CR_DATE,ORDER_QTY;
I need the next result in only 1 query:
if the order_priority<40 than the order will be the first according to the order by
but if order_priority>=40 than these data will be after the lower priority (first conditional /op<40/).
Result:
You can add this to your order by clause:
case when ORDER_PRIORITY<40 then 0 else 1 end
The final query will be:
SELECT
*
FROM SAMPLE
WHERE ORDER_PRIORITY>=40
ORDER BY
case when ORDER_PRIORITY<40 then 0 else 1 end,
FS_GENERATE_DATE IS NOT NULL, FS_GENERATE_DATE,ORDER_PRIORITY,CREATE_ID,CR_DATE,ORDER_QTY;
You are clearly using a database where booleans are allowed in the ORDER BY. So, you can just use:
SELECT S.*
FROM SAMPLE S
ORDER BY (ORDER_PRIORITY < 40) DESC,
FS_GENERATE_DATE IS NOT NULL,
FS_GENERATE_DATE,
ORDER_PRIORITY,
CREATE_ID, CR_DATE, ORDER_QTY;

Random sorting with ORDER BY with CASE clause

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.

Impala SQL, return value if a string exists within a subset of values

I have a table where the id field (not a primary key) contains either 1 or null. Over the past several years, any given part could have been entered multiple times with one, or both of these possible options.
I'm trying to write a statement that will return some value if there is ever a 1 associated with the select statement. There are lots of semi-duplicate rows, some with 1 and some with null, but if there is ever a 1, I want to return true, and if there are only null values, I want to return false. I'm not sure how to code this though.
If this is my SELECT part,id from table where part = "ABC1234" statement
part id
ABC1234 1
ABC1234 null
ABC1234 null
ABC1234 null
ABC1234 1
I want to write a statement that returns true, because 1 exists in at least one of these rows.
The closest I've come to this is by using a CASE statement, but I'm not quite there yet:
SELECT
a1.part part,
CASE WHEN a2.id is not null
THEN
'true'
ELSE
'false'
END AS id
from table.parts a1, table.ids a2 where a1.part = "ABC1234" and a1.key = a2.key;
I also tried the following case:
CASE WHEN exists
(SELECT id from table.ids where id = 1)
THEN
but I got the error subqueries are not supported in the select list
For the above SELECT statement, how do I return 1 single line that reads:
part id
ABC1234 true
You can use conditional aggregation to check if a part has atleast one row with id=1.
SELECT part,'True' id
from parts
group by part
having count(case when id = 1 then 1 end) >= 1
To return false when the id's are all nulls use
select part, case when id_true>=1 then 'True'
when id_false>=1 and id_true=0 then 'False' end id
from (
SELECT part,
count(case when id = 1 then 1 end) id_true,
count(case when id is null then 1 end) id_false,
from parts
group by part) t

Check and Change for empty or null value of column in SQL?

How can I change column text Not Exists when it is empty or null ?
My query :
Select TOP 1 ISNULL(NULLIF(DR.Name,''),'Not Exists') as Name,
DR.Name as Name ,Coalesce(NullIf(rtrim(DR.Name),''),'Not Exist') as Name,
Name = case when DR.Name is null then 'Not Exists'
when DR.Name='' then 'Not Exists' else DR.Name end
from Transfer TR
join Driver DR on DR.OID=TR.DriverID
WHERE TR.TruckID=51 AND TR.Statues<>7 and TR.DateScheduled<GETDATE()
AND TR.DateScheduled>=DATEADD(DAY,-7,GETDATE()) ORDER BY TR.OID DESC
Result :
If you just need a single column, then you can use a sub-select, this way when no rows are returned by the query you will still get not exists:
SELECT Name = ISNULL(( SELECT TOP 1 NULLIF(DR.Name,'')
FROM Transfer AS TR
INNER JOIN Driver AS DR
ON DR.OID = TR.DriverID
WHERE TR.TruckID = 51
AND TR.Statues <> 7
AND TR.DateScheduled < GETDATE()
AND TR.DateScheduled >= DATEADD(DAY, -7, GETDATE())
ORDER BY TR.OID DESC), 'Not Exists');
If you need multiple columns then you could union your Not Exists record to the bottom of the query, place all this inside a subquery then select the top 1 again, ensuring that your actual value takes precedence (by adding the column SortOrder):
SELECT TOP 1 Name, SomeOtherColumn
FROM ( SELECT TOP 1
Name = NULLIF(DR.Name,''),
SomeOtherColumn,
SortOrder = 0
FROM Transfer AS TR
INNER JOIN Driver AS DR
ON DR.OID = TR.DriverID
WHERE TR.TruckID = 51
AND TR.Statues <> 7
AND TR.DateScheduled < GETDATE()
AND TR.DateScheduled >= DATEADD(DAY, -7, GETDATE())
ORDER BY TR.OID DESC
UNION ALL
SELECT 'Not Exists', NULL, 1
) AS t
ORDER BY SortOrder;
I'm not entirely sure I understand your question, but if you are trying to catch nulls and empty strings "in one go", try this:
select TOP 1
case when length(trim(coalesce(DR.Name, ''))) = 0 then
'Not Exists'
else
DR.Name
as Name
....
The coalesce catches the NULLs and sets a replacement value. The trim gets rid of any padding and the length checks if what is left is an empty string --> so this covers nulls, padded- and non-padded trivial strings.
Assuming the value has regular spaces, the following would keep your approach:
Select TOP 1 ISNULL(NULLIF(ltrim(rtrim((DR.Name))), ''), 'Not Exists') as Name,
I would probably go with the more explicit:
select top 1 (case when ltrim(rtrim((DR.Name)) = '' or DR.Name is null then 'Not Exists'
else DR.Name end) as Name
Unless you also wanted the spaces removed from Name in the output.
If you have other characters, then you can use ASCII() to find them. Something like:
select ASCII(LEFT(DR.Name, 1))
. . .
where LEFT(DR.Name, 1) NOT LIKE '[a-zA-Z0-9 ]' -- you can expand this list of allowed characters
It seems to me you are not actually looking for a way to replace an empty string with 'Not Exists', but an empty result set.
In other words: It looks like you are looking for a way to show 'Not Exists' in case your query returns no rows. If it is this what you are looking for, then first "add" a 'Not Exists' record to your result set and then show the best row, i.e. the desired row in case such a row exists, else your 'Not Exists' row.
select top 1 name
from
(
select name, tr.oid
from transfer tr
join driver dr on dr.oid=tr.driverid
where tr.truckid=51 and tr.statues<>7 and tr.datescheduled<getdate()
and tr.datescheduled>=dateadd(day,-7,getdate())
union all
select 'Not Exists', -1
)
order by oid desc;
I chose -1 for the dummy OID. It must be a value smaller than any real OID. So if you have negative values, make that value even smaller.