Oracle: Handling Null In Case Statement - sql

I have a huge query used within a case-when block.
My query looks like this:
SELECT 'TEST' FROM DUAL WHERE 1=1 AND EXISTS(
SELECT
CASE
WHEN EXISTS
(Select 1 from dual where 1=2)
THEN 1
ELSE
(Select 1 from dual where 1=2)
END
FROM DUAL);
I want to execute my select-statement only if the case-when statement returns a record. However, it always prints 'Test' because this code always return a NULL:
SELECT
CASE
WHEN EXISTS
(Select 1 from dual where 1=2)
THEN 1
ELSE
(Select 1 from dual where 1=2)
END
So basically I want to print "TEST" only if no record (or null value) is returned. How can I achieve this?

A row with one column that has a NULL value is not the same as a non-existing row. So, you cannot do exactly what you want using EXISTS. One method is to do:
SELECT 'TEST'
FROM DUAL
WHERE 1 = 1 AND
1 = (SELECT CASE WHEN EXISTS(Select 1 from dual where 1=2)
THEN 1
ELSE 0
END
FROM DUAL
);
That is, look for a particular value, rather than check for the existence of a row.

We can use the following to handle the NULL
CASE TRIM(Your Field) IS NULL
THEN 'The value you want to show/ print'

Related

Looking for best way to execute Yes/No Query check in select statement

I was wondering if anyone could recommend the best way to execute this. I will introduce you to what I'm working on.
I've written a select query with some sub-queries which gets order records, I have a number business logic that these orders need to meet so that they come up on the report.
Additionally I've added a nested case statement which helps me determine is the business logic is met and it simply returns a Yes or a No. So far all looks great!
E.G.
Above is just a sample result for one order (29817). What I need to do next is only show Order_No when NOYESCHECK returns all YES's.
Nested Case statement:
(case when sm.supply_code='Project Inventory' and
(select po.order_no
from purchase_order_line_all po
where po.contract = sm.contract
and po.part_no = sm.part_no
and po.activity_seq = sm.activity_seq
and po.project_id = sm.project_id
and po.state in ('Closed','Arrived','Recieved') order by po.date_entered desc fetch first 1 row only) is not null then 'YES'
when sm.supply_code='Invent Order' and
( select sum(QTY_ONHAND - QTY_RESERVED)
from inventory_part_in_stock ipis
where ipis.contract = sm.contract
and ipis.part_no = sm.part_no
and ipis.QTY_ONHAND - ipis.QTY_RESERVED > '0'
and ipis.project_id is null
and ipis.AVAILABILITY_CONTROL_ID not in ('QUARANTINE','RD','TRANSIT','PRE SCRAP')
) is not null then 'YES'
else 'NO' end)NoYesCheck
What would be the best way to achieve this? I have tried using ALL operator but it didn't work quite as expected. What I tried with ALL operator:
and 'YES' = ALL (case when sm.supply_code='Project Inventory' and
(select po.order_no
from purchase_order_line_all po
where po.contract = sm.contract
and po.part_no = sm.part_no
and po.activity_seq = sm.activity_seq
and po.project_id = sm.project_id
and po.state in ('Closed','Arrived','Recieved') order by po.date_entered desc fetch first 1 row only) is not null then 'YES'
when sm.supply_code='Invent Order' and
( select sum(QTY_ONHAND - QTY_RESERVED)
from inventory_part_in_stock ipis
where ipis.contract = sm.contract
and ipis.part_no = sm.part_no
and ipis.QTY_ONHAND - ipis.QTY_RESERVED > '0'
and ipis.AVAILABILITY_CONTROL_ID not in ('QUARANTINE','RD','TRANSIT','PRE SCRAP')
and ipis.project_id is null
) is not null then 'YES'
else 'NO' end)
It seemed to return only lines with 'YES' in my check but the purpose here is:
If check is done per order and returns at least one 'No' then do not show the order. So in above image this order was never meant to show up as a result in my query but it did. So I'm a little stuck.
Any help would be appreciated. Let me know if I need to provide more info.
Thanks,
Kasia
You can use your NOYESCHECK column in a subselect within the where clause combined with a NOT IN check.
Psuedo code:
select
--main query columns
from data_source
where key_column not in (
select distinct
key_column
from (
select
key_column,
noyescheck_column
from data_source
where noyescheck_column = 'NO'
)
)
Would this help? See comments within code.
SQL> with
2 -- this is what your query currently returns
3 test (order_no, component_part, noyescheck) as
4 (select 29817, 100, 'NO' from dual union all
5 select 29817, 101, 'YES' from dual union all
6 --
7 select 30000, 200, 'YES' from dual union all
8 select 30000, 201, 'YES' from dual union all
9 --
10 select 40000, 300, 'NO' from dual
11 ),
12 -- find ORDER_NOs whose NOYESCHECK = YES only
13 yess as
14 (select order_no
15 from test
16 group by order_no
17 having min(noyescheck) = max(noyescheck)
18 and min(noyescheck) = 'YES'
19 )
20 -- return only ORDER_NOs that satisfy condition
21 select t.*
22 from test t join yess y on y.order_no = t.order_no;
ORDER_NO COMPONENT_PART NOY
---------- -------------- ---
30000 200 YES
30000 201 YES
SQL>

Compare 1 field from sub query against other?

I am trying to compare two fields in oracle select query as part of case statement one of which is coming from sub query but I get error.
E.g
select 1 as one,
(select 2 from dual) as two,
case when one=two then 'EQUAL'
else 'NOTEQUAL'
end match
from dual;
Error ORA-00904: TWO invalid identifier
Thoughts how can rewrite this?
Thanks in advance!
You cant use the alias, so you have to rewrite the data source and subquery.
SELECT 1 as one,
(SELECT 2 FROM dual) as two,
CASE WHEN 1 = (SELECT 2 FROM dual)
THEN 'EQUAL'
ELSE 'NOTEQUAL'
END match
FROM dual
Result
one two match
1 2 NOTEQUAL
The problem is you cant use the alias on the same level, you need to do a subquery or a cte
WITH step1 as (
select 1 as one
from dual
), step2 as (
select 2 as two
from dual
)
SELECT case when one=two then 'EQUAL'
else 'NOTEQUAL'
end match
FROM step1
CROSS JOIN step2
Use a simple subquery
Select t.*,
case when one=two then 'EQUAL'
else 'NOTEQUAL'
end match
From (
select 1 as one,
(select 2 from dual) as two
from dual
) t;

ORACLE: USE RESULT OF CASE-WHEN-STATEMENT

I have a huge query and I am wondering if it is in Oracle possible
to get the result of a case-when-statement and use it for comparison? My CASE-STATEMENT is declared in the Select-Statement and it looks like this.
SELECT........
(CASE
WHEN (Select 1 from DUAL) = 1 THEN 'TEST'
ELSE 'TEST2'
END) AS TEST;
Now I want to get the result of this case-statement and use it in the where part? Is it possible? (Sry this may be a dumb question)
If you define your CASE statement in either an inline-view or a common table expression (aka WITH clause), you can refer to it by whatever alias you give it.
For example (inline-view):
SELECT ...
FROM ( SELECT .....
(CASE
WHEN (Select 1 from DUAL) = 1 THEN 'TEST'
ELSE 'TEST2'
END) AS TEST
FROM...
) v
WHERE v.test = 'TEST2';
As a common table expression, it would be:
WITH cte AS ( SELECT........
(CASE
WHEN (Select 1 from DUAL) = 1 THEN 'TEST'
ELSE 'TEST2'
END) AS TEST
FROM ... )
SELECT ...
FROM cte
WHERE test = 'TEST2';
You can use a case statement in the where clause, for eg.:
select * from table
where table.field = (CASE
WHEN (Select 1 from DUAL) = 1 THEN 'TEST'
ELSE 'TEST2'
END)
This will compare the value returned from the case statement with the table field.

ORACLE: SELECT VALUE IF

I am trying to select different values that depend on different conditions, but I don't exactly know, how one can achieve this in SQL/Oracle..
Here is an example:
SELECT VALUE (I dont exactly know what to write here)
FROM
(SELECT
(CASE
WHEN (Select 1 from DUAL) = 1 THEN 'TEST'
WHEN (Select 1 from DUAL) = 0 THEN 'TEST1'
WHEN (Select 1 from DUAL) = 0 THEN 'TEST2'
ELSE 'N/A'
END)
FROM DUAL);
I want to print different results according to the conditions...For instance, in the example above it should print "TEST"
You need to provide an alias to the CASE statement:
SELECT alias_for_your_case_value
FROM (
SELECT CASE (Select 1 from DUAL)
WHEN 1 THEN 'TEST'
WHEN 0 THEN 'TEST1'
WHEN 0 THEN 'TEST2'
ELSE 'N/A'
END AS alias_for_your_case_value
FROM DUAL
);

Can Oracle PL/SQL CASE statement include a SELECT query?

I'm trying to do something similar to this:
CASE
WHEN number IN (1,2,3) THEN 'Y' ELSE 'N' END;
Instead I want to have a query in the place of the list, like so:
CASE
WHEN number IN (SELECT num_val FROM some_table) THEN 'Y' ELSE 'N' END;
I can't seem to get this to work. Also, here is an example of the query.
SELECT number, (CASE
WHEN number IN (SELECT num_val FROM some_table) THEN 'Y' ELSE 'N' END) AS YES_NO
FROM some_other_table;
Yes, it's possible. See an example below that would do what you are intending. The difference is that it uses EXISTS instead of IN.
SELECT a.number,
(CASE WHEN EXISTS (SELECT null FROM some_table b where b.num_val = a.number)
THEN 'Y'
ELSE 'N'
END) AS YES_NO
FROM some_other_table a;
EDIT:
I confess: I like the answers given by the others better personally.
However, there will be a difference between this query and the others depending on your data.
If for a value number in the table some_other_table you can have many matching entries of num_val in the table some_table, then the other answers will return duplicate rows. This query will not.
That said, if you take the left join queries given by the others, and add a group by, then you won't get the duplicates.
I suggest using an OUTER JOIN instead of trying to use a subquery in a CASE expression:
SELECT t.NUMBER,
CASE
WHEN s.NUM_VAL IS NOT NULL THEN 'Y'
ELSE 'N'
END AS YES_NO
FROM SOME_OTHER_TABLE t
LEFT OUTER JOIN SOME_TABLE s
ON s.NUM_VAL = t.NUMBER
Best of luck.
Seems like you just need to join the tables and do a decode.
with x as
(
select 1 as num from dual
union
select 2 as num from dual
union
select 3 as num from dual
),
y as
(
select 1 as num from dual
union
select 2 as num from dual
union
select 4 as num from dual
)
select x.num, decode(y.num, null, 'N','Y') as yes_no
from x
left outer join y on (x.num = y.num)
Output:
NUM YES_NO
1 Y
2 Y
3 N
You can use subquery in case statement:
select
case dummy
when 'X' then (select 'TRUE' from dual)
else 'FALSE'
end TEST
from dual;
TEST
TRUE
select
case (select 'XXX' from dual)
when 'XXX' then 'TRUE'
else 'FALSE'
end TEST
from dual;
TEST
TRUE