IBM DB2 Case in Where clause? - db2

I have a SQL Statement where I have to check on conditions on rows since it has duplicates.
Condition1 is to watch if the value from a column in tb1 is between two values in a two columns of tb2 but only on rows which has a 'Y' inside.
I have something like this:
SELECT DISTINCT
tb1.columnA, tb1.columnB, tb2.columnA, tb2.columnB,
CASE
WHEN tb1.col1 = 'Y'
THEN CONCAT(tb1.col2,tb2.col2)
ELSE 'no changes'
END as conditionColumn
FROM
tb1 left outer join tb2 on tb1.columnX tb2.columnX
WHERE
CASE
WHEN tb1.col1 = 'Y'
THEN Condition1
ELSE Condition2
END
From what I saw before, a case statement is not allowed in the where clause?
How can I handle this then?
EDIT
When I have a 'Y' in tb1.col1
the where clause should output me an ID specified in tb1.columnA and only the rows which values from tb1.ColumnB is between tb2.columnA and tb2.columnB. If it doesn't have a Y inside then it should simply just give me the ID
so I used this, but it gives me an syntax error:
SELECT DISTINCT
tb1.columnA, tb1.columnB, tb2.columnA, tb2.columnB,
CASE
WHEN tb1.col1 = 'Y'
THEN CONCAT(tb1.col2,tb2.col2)
ELSE 'no changes'
END as conditionColumn
FROM
tb1 left outer join tb2 on tb1.columnX tb2.columnX
WHERE
CASE
WHEN tb1.col1 = 'Y'
THEN tb1.columnA = 'MyID'
AND tb1.columnB BETWEEN tb2.columnA and tb2.columnB
ELSE tb1.columnA = 'MyID'
END

If you want to do this
WHERE
CASE
WHEN tb1.col1 = 'Y'
THEN Condition1
ELSE Condition2
END
then, likely what you are wanting is this
WHERE
( tb1.col1 = 'Y' AND Condition1 )
OR ( tb1.col1 <> 'Y' AND Condition2 )

You seem to be confused about the purpose of a WHERE clause...
All a WHERE clause does is decide rather or not a given row is returned. It can't change the data being returned.
To change the data, you need a CASE in the columns selected...
something like so...
SELECT DISTINCT
CASE
WHEN tb1.col1 = 'Y'
AND tb1.columnB BETWEEN tb2.columnA and tb2.columnB
then 'MyID'
ELSE tb1.columnA
END as newColumnA,
tb1.columnB, tb2.columnA, tb2.columnB,
CASE
WHEN tb1.col1 = 'Y'
THEN CONCAT(tb1.col2,tb2.col2)
ELSE 'no changes'
END as conditionColumn
FROM
tb1 left outer join tb2 on tb1.columnX tb2.columnX

Related

Using Case Statement when there is no entries in table

I want to fulfill below condition for a field in the left outer join
If the field1 = Open and field2 ne 3 then I need 'OPEN'
else 'CLOSE'
and there is no entry in the table then i need 'NEUTRAL'
this is the coding written but it returns either OPEN and CLOSE but not neutral if table3 doesnt have entry based on join condition which is given below.
Kindly help.
SELECT coalesce ( (
case
when tab3.field1 = 'Open' and tab3.field2 <> '3' then 'OPEN'
else 'CLOSE'
end
),'NEUTRAL') as STATUS
FROM table1 AS tab1
LEFT OUTER JOIN table3 AS tab3
on tab1.material = tab3.material
You wanting something like this:
case
when tab3.material is null then 'NEUTRAL'
when tab3.field1 = 'Open' and tab3.field2 <> '3' then 'OPEN'
else 'CLOSE'
end as Status

DB2 How to use case with multiple conditions?

I have a DB2 Server and I want to select data depending on the condition.
If I have the Value Value in the ColumnX, ColumnY or ColumnZ it should search for it between the TB2.Column1 and TB3.Column1
My statement is a bunch of left outer joins but it looks like that:
SELECT
CASE
WHEN (TB1.ColumnX || TB1.ColumnY || TB1.ColumnZ) = 'Value'
THEN Statement1
ELSE ' '
END AS MyColumn
FROM
TB1 LEFT OUTER JOIN TB2 ON TB1.JOINCOL = TB2.JOINCOL
LEFT OUTER JOIN TB3 ON TB2.JOINCOL2 = TB3.JOINCOL
WHERE TB1.Column1 between TB2.Column1 and TB3.Column1
But it doesn't work, is there a mistake in the syntax?
It is not possible to check for multiple equalities using just a single expression. You may use the following syntax trick:
CASE WHEN 'Value' IN (TB1.ColumnX, TB1.ColumnY, TB1.ColumnZ)
THEN Statement1 ELSE ' ' END AS MyColumn
The alternative to this would be to repeat the full equality check for each column:
SELECT
CASE
WHEN TB1.ColumnX = 'Value' OR
TB1.ColumnY = 'Value' OR
TB1.ColumnZ = 'Value'
THEN Statement1
ELSE ' '
END AS MyColumn
FROM
TB1 LEFT OUTER JOIN TB2
ON TB1.JOINCOL = TB2.JOINCOL
LEFT OUTER JOIN TB3
ON TB2.JOINCOL2 = TB3.JOINCOL
WHERE
TB1.Column1 BETWEEN TB2.Column1 AND TB3.Column1;
If you need to refer to the CASE expression in the WHERE clause, then you have two choices. First, you may subquery your current query, and assign an alias to the CASE expression:
SELECT *
FROM
(
SELECT CASE WHEN ... AS exp
FROM TB1 ...
) t
WHERE exp = ...
Or, you may avoid the subquery and just repeat the entire CASE expression in the WHERE clause.

Optimise case/decode query in Postgres

Can anyone help me to implement the below query in another way? I am facing a performance issue because the same multiple SELECT statements are used everywhere in multiple CASE statements.
My code is very big, a chunk of it is here:
select col1,col2,
( CASE
WHEN NOT EXISTS (SELECT
CASE over.ola
WHEN NULL::text THEN 'NT'::character varying
END AS tover
FROM tsmt over
WHERE over.cod = hfprc.cod
AND over.vdat = nav.vdat) THEN 'NT'
ELSE (SELECT CASE over.ola
WHEN NULL::text THEN 'TT'::character varying END
FROM tsmt over
WHERE over.cod = hfprc.cod
AND over.vdat = nav.vdat)
END )
olaflag,
(SELECT description
FROM tolahfp tover
WHERE tover.ola = (SELECT CASE
WHEN NOT EXISTS (SELECT
CASE over.ola
WHEN NULL::text THEN 'TT'::character varying
END AS
tover
FROM tsmt over
WHERE over.cod = hfprc.cod
AND over.vdat = nav.vdat) THEN 'TT'
ELSE (SELECT CASE over.ola
WHEN NULL::text THEN 'TT'::character varying
END AS tover
FROM tsmt over
WHERE over.cod = hfprc.cod
AND over.vdat = nav.vdat)
END ola
))
ola,--ola description
(CASE thfp.codcag::text
WHEN NULL::text THEN 'CCCC'::character varying
END
)codcag,
(SELECT conf.descag
FROM thfconagrhfp conf
WHERE conf.codcag = CASE thfp.codcag::text
WHEN NULL::text THEN 'CCCC'::character varying
END)
desccag,
thfp.frq,
thfp.flgcal
FROM thpr hfprc LEFT JOIN tgrpprchfp grp ON hfprc.cgrp = grp.cgrp
LEFT JOIN tnav nav ON hfprc.cod = nav.cod AND nav.flag = 'Y'
LEFT JOIN thf thfp ON hfprc.cod = thfp.cod
LEFT JOIN tsmtdatthdhfp smtdatthd ON hfprc.cod = smtdatthd.cod
Do you use sqlsmith to write your queries?
But, more seriously, the way forward here is to replace subselects with outer joins.
As an example:
SELECT CASE WHEN NOT EXISTS (SELECT weirdfunc(x.x1)
FROM x
WHERE x.x2 = y.y2
AND x.x3 = z.z3)
THEN 'Constant'
ELSE (SELECT otherweirdfunc(x.x1)
FROM x
WHERE x.x2 = y.y2
AND x.x3 = z.z3)
END
FROM y
LEFT JOIN z USING (t);
would be better and more efficiently be written as
SELECT coalesce(otherweirdfunc(x.x1), 'Constant')
FROM y
LEFT JOIN z USING (t)
LEFT JOIN x ON x.x2 = y.y2 AND x.x3 = z.z3;
My rule of thumb is: subselects are usually wrong anywhere except in the FROM clause.

How to optimize CASE statement in SELECT query which has same check condition for three different columns

I have below select statement to fetch the data having CASE statement.
SELECT PK_ID
,MGR_ID
,EMP_ID
,CASE
WHEN msts.MGR_ID is null AND msts.EMP_ID is not null THEN
(SELECT 'A' from dual)
ELSE
(SELECT 'B' from dual)
END FIRST_COL
,CASE
WHEN msts.MGR_ID is null AND msts.EMP_ID is not null THEN
(SELECT 'P' from dual)
ELSE
(SELECT 'Q' from dual)
END SECOND_COL
,CASE
WHEN msts.MGR_ID is null AND msts.EMP_ID is not null THEN
(SELECT 'X' from dual)
ELIE
(SELECT 'Y' from dual)
END THIRID_COL
from m_sel_tabs msts
here, As i know that we can check condition with mulitiple columns but the result will be only one for CASE statement.
so my question is here that as my check CASE statement is the same for all three columns (FIRST_COL, SECOND_COL, THIRID_COL), hence is there any other way to write this query in an optimized way.
Thanks in advance.
Maybe I'm wrong, but - when saying that you have "the same 3 CASE statements" - well, you don't. Those are 3 different CASE statements. An expression is the same, yes, but you're selecting 3 different columns, with different results (A, B, P, Q, X, Y - in your example).
You could create a function which would "hide" code you currently use and make the SELECT prettier, such as
select
pk_id, ...,
f_col(1, MGR_ID, EMP_ID) first_col,
f_col(2, MGR_ID, EMP_ID) second_col,
f_col(3, MGR_ID, EMP_ID) third_col
from m_sel_tabs
but - at the end - it would be just the same (or, possibly somewhat worse because of context switching) as you'd have to put all that code somewhere (into the function, right?).

CTE with CASE statement

I'm trying a query like this;
WITH CTE AS
(
SELECT
ID, NAME, DEPT,
CASE WHEN Fixed = 1 THEN 'Yes' ELSE '' END,
CASE WHEN NotFixed = 1 THEN 'Yes' ELSE '' END,
)
When I try to execute this query, I'm getting error like
No Column was specified for column 4 of CTE
What's wrong with the query?
Read the error message: You forgot to give your calculated columns a name. This goes for both column 4 and column 5. So change your query to something like this:
WITH CTE AS
(
SELECT
ID, NAME, DEPT,
CASE WHEN Fixed = 1 THEN 'Yes' ELSE '' END AS [Expr1],
CASE WHEN NotFixed = 1 THEN 'Yes' ELSE '' END AS [Expr2],
. . .
)
Feel free to change [Expr1] and [Expr2] to something more meaningful...