The below Case Statement is part of an Select Query.
Is it safe to remove when not part in this case statement ?
Can the when not part removed ?
Will removing the when not , will have any difference ?
WHERE
CASE
WHEN o.order_id <> '0' THEN
CASE
WHEN (
a.acc_id IS NULL
AND
o.order_status = ‘a’
)
THEN
1
WHEN NOT (
a.acc_id IS NULL
AND
o.order_status = ‘a’
)
THEN
0
END
ELSE CASE
WHEN (
(
o.order_id = '0'
)
AND
a.acc_id IS NULL
AND
o.order_status = ‘a’
)
THEN
1
WHEN NOT (
(
o.order_id = '0'
)
AND
a.acc_id IS NULL
AND
o.order_status = ‘a’
)
THEN
0
END
END
= 1
Your inner CASE expression:
CASE
WHEN (a.acc_id IS NULL AND o.order_status = 'a')
THEN 1
WHEN NOT (a.acc_id IS NULL AND o.order_status = 'a')
THEN 0
END
Produces 3 different values 1, 0 and NULL.
1 when a.acc_id IS NULL AND o.order_status = 'a'
0 when a.acc_id IS NOT NULL OR o.order_status != 'a'
NULL when o.order_status IS NULL
If you replace the second WHEN clause with an ELSE clause then you will not get the same logic as there will only be 2 values output by the CASE expression.
However, in the outer comparison, neither 0 = 1 or NULL = 1 will match so although you change the logic of the inner CASE expression by removing the WHEN NOT (...) clause you will not change the overall logic of the statement.
You can simplify it all to:
WHERE ( o.order_id <> '0'
AND a.acc_id IS NULL
AND o.order_status = 'a'
)
OR ( o.order_id = '0' -- There should be an OR o.order_id IS NULL
-- filter here but it is eliminated by the
-- inner CASE expression in your code.
AND a.acc_id IS NULL
AND o.order_status = 'a'
)
Which simplifies further to:
WHERE o.order_id IS NOT NULL
AND a.acc_id IS NULL
AND o.order_status = 'a'
If you want it in a CASE expression then:
WHERE CASE
WHEN o.order_id IS NOT NULL
AND a.acc_id IS NULL
AND o.order_status = 'a'
THEN 1
END = 1
(but the CASE expression seems pointless.)
You have a case when returning 1 and a when not (same criteria) to return 0. Case when defaults to null for scenarios that are not covered. So, if you remove the when not part, then the expression will evaluate to null instead of 0 and null=1 will filter out the records having such values. So, it seems that it will not be harmful to remove the when not part, but it will be less readable. I would use else 0 instead of the when not:
WHERE
CASE
WHEN o.order_id <> '0' THEN
CASE
WHEN (
a.acc_id IS NULL
AND
o.order_status = ‘a’
)
THEN
1
ELSE
0
END
ELSE CASE
WHEN (
(
o.order_id = '0'
)
AND
a.acc_id IS NULL
AND
o.order_status = ‘a’
)
THEN
1
ELSE
0
END
END
= 1
Related
I have the below Pivot and output. I would like to display the below.
Remove the parentheses around the columns?
Add indicator of X and Null in substitute of 1 and 0?
SQL:
SELECT DISTINCT
*
FROM (
SELECT D.ID, D.DI, A.ID
FROM A
LEFT JOIN AD ON A.ID = AD.ID
LEFT JOIN D ON AD.ID = D.ID
WHERE 1=1
AND A.ID = 890929
)
PIVOT
(
COUNT(ID)
FOR DI IN ( 'Low med','Soft','Regular','High Med','Other')
)
Query output:
ID 'Low med' 'Soft' 'Regular' 'High Med' 'Other'
1 1 1 0 0 1
Expected output:
ID LOW_MED SOFT REGULAR HIGH_MED OTHER
1 X X NULL NULL X
You can remove the single quotes (not parentheses, which are ()), by aliasing the pivoted expressions:
FOR DI IN ('Low med' as low_med, 'Soft' as soft, 'Regular' as regular,
'High Med' as high_med,'Other' as other)
You can then use those aliases for the second part, but adding case expressions to your main query:
SELECT id,
case when low_med = 1 then 'X' else null end as low_med,
case when soft = 1 then 'X' else null end as soft,
case when regular = 1 then 'X' else null end as regular,
case when high_med = 1 then 'X' else null end as high_med,
case when other = 1 then 'X' else null end as other
FROM (
SELECT D.ID, D.DI, A.ID
FROM A
LEFT JOIN AD ON A.ID = AD.ID
LEFT JOIN D ON AD.ID = D.ID
WHERE 1=1
AND A.ID = 890929
)
PIVOT
(
COUNT(ID)
FOR DI IN ('Low med' as low_med, 'Soft' as soft, 'Regular' as regular,
'High Med' as high_med,'Other' as other)
)
I need to update the the following columns in a table. males,females,infants and children using SQL procedure.from this column paxtype which has f,i,m,c.which is females,infants,males and children repectively.but am not able error ORA-00907: missing right parenthesis
update xxxx a set (a.INFANTS,a.MALES,a.CHILDREN,a.FEMALES)=
(SELECT b.PAXTYPE, COUNT (b.PAXTYPE) FROM xxxx b
(case ( count (b.PAXTYPE))
when ( count (b.PAXTYPE))='M'then 'a.males'
when ( count (b.PAXTYPE))='F' then 'a.females'
when ( count (b.PAXTYPE))='I' then 'a.infants'
when ( count (b.PAXTYPE))='C' then 'a.children'
END)
WHERE a.date_key = TO_CHAR (b.FLIGHTDATE, 'RRRRMMDD')
AND a.FLTNUM_KEY = TRIM (SUBSTR (b.flightnumber, 3))
AND a.origin = b.frm
AND a.destination = b.too
--and a.date_key=20170801
--and fightnumber = '100'
AND TRIM (a.cancelled) IS NULL
-- and rownum = 1
GROUP BY b.PAXTYPE;
)
It looks like you want a total count of each type, right? I think this is what you want to do.
update xxxx a set (a.INFANTS,a.MALES,a.CHILDREN,a.FEMALES)=
(SELECT
sum(case when b.PAXTYPE = 'I' then 1 else 0 end) as infants_count,
sum(case when b.PAXTYPE = 'M' then 1 else 0 end) as males_count,
sum(case when b.PAXTYPE = 'C' then 1 else 0 end) as children_count,
sum(case when b.PAXTYPE = 'F' then 1 else 0 end) as females_count
FROM xxxx b
WHERE a.date_key = TO_CHAR (b.FLIGHTDATE, 'RRRRMMDD')
AND a.FLTNUM_KEY = TRIM (SUBSTR (b.flightnumber, 3))
AND a.origin = b.frm
AND a.destination = b.too
--and a.date_key=20170801
--and fightnumber = '100'
AND TRIM (a.cancelled) IS NULL
-- and rownum = 1
GROUP BY b.PAXTYPE);
I have a table like "Emp_Info", For the below output i have used "two" SELECT Statements, I want work that using ONE SELECT STATEMENT.
select count(*) into cnt
from emp_info t
where upper(trim(t.email)) = upper(trim(field1value))
and t.company_id = companyId;
select
(case when cnt1 > 0 then 'YES' else 'NO' end) into val_acc
from (
select count(*) cnt1 from
emp_info t
where upper(trim(t.email)) = upper(trim(field1value))
and (t.account_expiry_dt is null or t.account_expiry_dt >= sysdate)
and t.company_id = companyId
);
if cnt = 0 then
raise_application_error(-20002, 'User does not exist');
elsif cnt > 1 then
raise_application_error(-20003, 'Duplicate records found');
elsif val_acc = 'NO' then
raise_application_error(-20004, 'Account has expired');
else
/* some logic */
end if;
end;
may be this help you
select count(*),
CASE WHEN
sum( CASE when t.account_expiry_dt is null or t.account_expiry_dt >= sysdate then 1 else 0 end) > 0 then 'YES'
else 'NO'
END
into cnt, val_acc
from emp_info t
where upper(trim(t.email)) = upper(trim(field1value))
and t.company_id = companyId;
simple demo:
with emp_info(login,username) as (select 'test', 'test' from dual union
select 'TEst', 'TEst' from dual )
select count(*) emp_count,
CASE when sum( CASE WHEN login like '%st%' then 1 else 0 end) > 0 then 'Y' else 'N' end emp_flag,
sum( CASE WHEN login like '%st%' then 1 else 0 end) emp_flag_count,
CASE when sum( CASE WHEN login like '%te%' then 1 else 0 end) > 0 then 'Y' else 'N' end emp_flag1,
sum( CASE WHEN login like '%te%' then 1 else 0 end) emp_flag_count1,
CASE when sum( CASE WHEN login like '%TE%' then 1 else 0 end) > 0 then 'Y' else 'N' end emp_flag2,
sum( CASE WHEN login like '%TE%' then 1 else 0 end) emp_flag_count2
from emp_info
answer if it helped you
I have this query
select devlocview.ENTERPRISENAME
FROM AlarmDeviceView alrmDevView
INNER JOIN devicelocationview devLocView
ON devlocview.oid=alrmdevview.deviceoid
LEFT OUTER JOIN DEVICEGROUPVIEW devGrpView
ON devlocview.oid=devgrpview.deviceoid
LEFT OUTER JOIN RackCapacityView rackCapView
ON devlocview.RACKID=rackCapView.oid
WHERE
(
alrmdevview.createddate = ( select max(alview.createddate)
from alarmdeviceview alview
WHERE alview.alarmoid=alrmdevview.alarmoid)
or alrmdevview.createddate IS NULL
)
AND devlocview.ENTERPRISENAME='Enterprise1'
AND devlocview.buildingname in (
CASE
WHEN $p{building} IS not NULL THEN $p{building}
WHEN $p{building} IS NULL THEN (select buildingname from cdmr.devicelocationview)
END
)
Here this part "select buildingname from cdmr.devicelocationview" returns multiple rows due to which I am getting
exception as 01427. 00000 - "single-row subquery returns more than
one row"
As per the requirement I want to assign multiple building when $p{building} is null
A CASE is a scalar expression, it must evaluate to a scalar value. You can't use it to return a multi-row set.
The most common idiom I've seen for varying the condition based on whether an input value is NULL would look like this for your example:
AND ( ( $p{building} IS NOT NULL AND devlocview.buildingname = $p{building} )
OR
( $p{building IS NULL AND devlocview.buildingname IN (SELECT buildingname FROM cdmr.devicelocationview ) )
)
try
AND 1 = case
when $p{building} IS not NULL
and devlocview.buildingname = $p{building}
then 1
when $p{building} IS NULL
AND devlocview.buildingname in (select buildingname from cdmr.devicelocationview)
then 1
else 0
end
instead of
when devlocview.buildingname in (
CASE
WHEN $p{building} IS not NULL THEN $p{building}
WHEN $p{building} IS NULL THEN (select buildingname from cdmr.devicelocationview)
END
)
I have a table that has 5 "optional" fields. I'd like to find out how many rows have all 5 null, how many have 1 field non-null, etc.
I've tried a couple of things, like:
select
count(*),
( (if field1 is null then 1 else 0) +
(if field2 is null then 1 else 0) +
etc.
but of course that doesn't work.
Ideally, I'm looking for output that's something like
Nulls Cnt
0 200
1 345
...
5 40
Is there an elegant solution?
The keyword is not if, it is case, and you must use end to end the case statement.
Here is a query that can suit you:
WITH subQuery AS
(
SELECT My_Table.*, (CASE WHEN My_Table.field1 IS NULL THEN 1 ELSE 0 END +
CASE WHEN My_Table.field2 IS NULL THEN 1 ELSE 0 END +
CASE WHEN My_Table.field3 IS NULL THEN 1 ELSE 0 END +
CASE WHEN My_Table.field4 IS NULL THEN 1 ELSE 0 END +
CASE WHEN My_Table.field5 IS NULL THEN 1 ELSE 0 END ) NumberOfNullFields
FROM My_Table
)
SELECT NumberOfNullFields, COUNT(*)
FROM subQuery
GROUP BY NumberOfNullFields;
While there is nothing wrong with the case WHEN counting, I just wanted to see if there was another way.
WITH SAMPLEDATA AS(--just generate some data with nulls for 5 cols
select level ,
(case when mod(level,2) = 0 then 1 else null end) colA,
(case when mod(level,3) = 0 then 1 else null end) colB,
(case when mod(level,5) = 0 then 1 else null end) colC,
(case when mod(level,7) = 0 then 1 else null end) colD,
(case when mod(level,11) = 0 then 1 else null end) colE
from dual
connect by level < 1000
), --utilize the count(Aggregate)'s avoidance of nulls to our summation advantage
nullCols as(
SELECT COUNT(COLA) aNotNull
,cOUNT(*)-COUNT(COLA) aNull
,count(colB) bNotNull
,cOUNT(*)-count(colB) bNull
,count(colc) cNotNull
,cOUNT(*)-count(colc) cNull
,count(cold) dNotNull
,cOUNT(*)-count(cold) dNull
,count(cole) eNotNull
,cOUNT(*)-count(cole) eNull
, cOUNT(*) TotalCountOfRows
from SAMPLEDATA )
SELECT (select count(*) from sampledata where cola is null and colb is null and colc is null and cold is null and cole is null) allIsNull
,nullCols.*
FROM nullCols;
ALLISNULL ANOTNULL ANULL BNOTNULL BNULL CNOTNULL CNULL DNOTNULL DNULL ENOTNULL ENULL TOTALCOUNTOFROWS
---------------------- ---------------------- ---------------------- ---------------------- ---------------------- ---------------------- ---------------------- ---------------------- ---------------------- ---------------------- ---------------------- ----------------------
207 499 500 333 666 199 800 142 857 90 909 999
this utilizes the
If expression in count(expression)
evaluates to null, it is not counted:
as noted from here
This method, as is obvious above, does not 'eloquently' sum all null columns well. Just wanted to see if this was possible without the CASE logic.