Case with multiple conditions on multiple columns - sql-server

I am trying to figure out how to make this work:
CASE
WHEN a.val IS NULL AND (a.CreatedBy <> 'MDI' OR a.Type <> 'RO' OR a.Unit <> 'ER') THEN 1
ELSE 0
END as field_name
Basically I am looking for rows where a.val is null, but ignore the row if any of these columns (a.CreatedBy or a.Type or a.Unit) have a specific value. Even if one of these columns is true for the specific value the case should return 0.
Is it possible? Thanks in advance.

You will need AND instead of OR operators.
CASE WHEN a.val IS NULL
AND a.CreatedBy <> 'MDI'
AND a.Type <> 'RO'
AND a.Unit <> 'ER'
THEN 1
ELSE 0
END as field_name

CASE WHEN A.VAL IS NULL AND
(A.CREATED_BY<>'MDI' OR A.TYPE<>'RO','AND A.UNIT<>'ER') THEN 1
ELSE 0 END
AS COLUMNNAME

Related

Parsing JSON value in a Snowflake Variant column to multiple columns based on condition

I am trying to parse below JSON data in column test_column from table table_a. If the label department has Electrical, dept_1 should be defaulted as 1, if label department has Electronics, dept_2 should be defaulted to 1, and if label department has Chemical, dept_3 should be defaulted to 1.
test_column
{"labels": {"department_id": "1","department": ["Electrical","Electronics","Chemical"]}}
{"labels": {"department_id": "2","department": ["Electrical"]}}
I used below query but it is not yielding what i want -
Query used:
select dept_id,
case when dept='Electrical' then 1 else NULL end as dep1,
case when dept='Electronics' then 2 else NULL end as dep2,
case when dept='Chemical' then 3 else NULL end as dep3
from(
SELECT
test_column:labels:department_id::varchar as dept_id,
array_to_string(test_column:labels:department,',') as dept
FROM table_a
);
Could you tell me what is going wrong? Am getting NULL for records having all 3 Eletrical, Eletronics, and Chemical.
Expected result:
dept_id
dept_1
dept_2
dept_3
1
1
1
1
2
1
NULL
NULL
You have 2 options to do this differently.
Option #1: Flatten your array and then re-aggregate back for your case statements:
WITH x AS (
SELECT parse_json('{"labels": {"department_id": "1","department": ["Electrical","Electronics","Chemical"]}}') as var
)
SELECT x.var:labels:department_id::integer as dept_id,
max(case when y.value::varchar='Electrical' then 1 else NULL end) as dep1,
max(case when y.value::varchar='Electronics' then 2 else NULL end) as dep2,
max(case when y.value::varchar='Chemical' then 3 else NULL end) as dep3
FROM x,
lateral flatten (input=>var:labels:department) y
group by 1;
Option #2 - since your case statement is just evaluating the presence of a value, you can just look at the array using a ARRAY_CONTAINS function to evaluate:
WITH x AS (
SELECT parse_json('{"labels": {"department_id": "1","department": ["Electrical","Electronics","Chemical"]}}') as var
)
SELECT x.var:labels:department_id::integer as dept_id,
case when array_contains('Electrical'::variant, var:labels:department::array) then 1 else NULL end as dep1,
case when array_contains('Electronics'::variant, var:labels:department::array) then 2 else NULL end as dep2,
case when array_contains('Chemical'::variant, var:labels:department::array) then 3 else NULL end as dep3
FROM x;
Please try the below query:
SELECT
test_column:labels:department_id::varchar as dept_id,
IFF(ARRAY_CONTAINS('Electrical'::VARIANT, test_column:labels:department), 1, NULL) as DEP_1,
IFF(ARRAY_CONTAINS('Electronics'::VARIANT, test_column:labels:department), 1, NULL) as DEP_2,
IFF(ARRAY_CONTAINS('Chemical'::VARIANT, test_column:labels:department), 1, NULL) as DEP_3
FROM table_a;

How to store result of CASE expression into (temporary/not) variable and use it to calculate concurrently inside the same SELECT statement

In other programing language we can do this:
A = 5
B = A + 7
But anyone know how to do this in SQL, something like this:
SELECT
(CASE WHEN (CASE WHEN t.[Id] IS NULL THEN 0 ELSE 1 END) = 1 THEN a.[123]
ELSE a.[432] END) AS 'Points',
#'Points' + 5 AS 'FinalPoints' ---Does any way to do this
FROM DeliveryOrder AS do
LEFT JOIN Transaction AS t ON t.DOId = do.Id
LEFT JOIN Amount AS a ON do.Id = a.Id
I really appreciate if anyone have any ideas how to do this
P/S: Since I can use SubQuery to simulate this but in my case, each columns have many CASE..WHEN expression and inside it have Case expression too so after all when combine all of them into single SubQuery make thing so terrible to read :(
You can't do exactly what you want. Aliases defined in the select clause cannot be reused in the same clause, so you need to either repeat the expression, or use a derived table (subquery or cte).
Your nested case seems overkill - I think that your code can be simplified as:
SELECT
CASE WHEN t.[Id] IS NULL THEN 10 ELSE 5 END AS points,
CASE WHEN t.[Id] IS NULL THEN 15 ELSE 10 END finalPoints
FROM DeliveryOrder AS do
LEFT JOIN Transaction AS t ON t.DOId = do.Id
Or using a subquery:
SELECT
points,
points + 5 finalPoints
FROM (
SELECT CASE WHEN t.[Id] IS NULL THEN 10 ELSE 5 END AS points
FROM DeliveryOrder AS do
LEFT JOIN Transaction AS t ON t.DOId = do.Id
) t
One another way can be to use cross apply,
SELECT
p.Points
,p.Points+5 'FinalPoints'
FROM DeliveryOrder AS do
LEFT JOIN dbo.[Transaction] AS t ON t.DOId = do.Id
cross apply (
select CASE WHEN T.Id IS NOT NULL THEN 5 ELSE 10 END AS 'Points'
) p
Using a SubQuery
SELECT Points, Points + 5 AS FinalPoints
FROM
(
SELECT CASE WHEN (CASE WHEN T.Id IS NULL THEN 0 ELSE 1 END) = 1 THEN 5 ELSE 10 END Points
FROM DeliveryOrder AS DO
LEFT JOIN [Transaction] AS T ON DO.Id = T.DOId
) T
You could get ride of the nested CASE expression and directly use
CASE WHEN T.Id IS NOT NULL THEN 5 ELSE 10 END Points

Using isnull() function and subquery

I have 2 separate columns, 'ATFTE' and 'SATFTE'. Using these two columns, I have to perform division and store the result in a separate column (say Pyramid). I am trying to use isnull function, because in many cases, the denominator is 0 and bringing it in a subquery. It shows error - 'Invalid Column name' - ATFTE and SATFTE. How can I rectify it?
select isnull(ATFTE/SATFTE,0) as Pyramid
from dw_UtilizationPredictionReport
where WFMGrade in (
select WFMGrade,
case
when WFMGrade IN ('P/PA','PAT','A') then sum(TotalFTE)
else 0
END as ATFTE,
case
when WFMGrade IN ('SA','M','SM','AD','D','SD','AVP','VP','SVP','EVP')
and WFMGrade NOT IN ('Cont') then sum(TotalFTE)
else 0
END as SATFTE
from dw_UtilizationPredictionReport
group by (WFMGrade)
)
select a.WFMGrade, sum(b.TotalFTE) / sum(c.(TotalFTE)
from dw_UtilizationPredictionReport a
left join dw_UtilizationPredictionReport b
on b.WFMGrade = a.WFMGrade
and b.WFMGrade IN ('P/PA','PAT','A')
left join dw_UtilizationPredictionReport c
on c.WFMGrade = a.WFMGrade
and c.WFMGrade IN ('SA','M','SM','AD','D','SD','AVP','VP','SVP','EVP')
group by a.WFMGrade
Try if this is working for you, you dont have to include not in for condition "Cont" since you are having the in condition.
Try this for the first bit
SELECT
CASE
WHEN ISNULL(SATFTE,0) = 0 THEN 0 -- Or whatever you want
ELSE ISNULL(ATFTE/SATFTE,0)
END AS Pyramid
Try this:
select CASE WHEN ISNULL(SATFTE,0) = 0 THEN 0
ELSE ISNULL(ATFTE/SATFTE,0)
END AS Pyramid FROM
(select WFMGrade,
case
when WFMGrade IN ('P/PA','PAT','A') then sum(TotalFTE)
else 0
END as ATFTE,
case
when WFMGrade IN ('SA','M','SM','AD','D','SD','AVP','VP','SVP','EVP')
and WFMGrade NOT IN ('Cont') then sum(TotalFTE)
else 0
END as SATFTE
from dw_UtilizationPredictionReport
group by (WFMGrade)) as tbl
In your query it seems that you have done below mistakes:
You can not use the IN statement with multiple columns in the WHERE
Clause.
ATFTE/SATFTE are not the columns of the table
"dw_UtilizationPredictionReport", so you can not use it in the
select.

Compare two columns ftp_start_time and ftp_stop_time and return the count of columns based on conditions

[Compare two columns ftp_start_time and ftp_stop_time and return the count of columns based on conditions :3 columns are 1.Tried(count(ftp_start_time)) 2.Success(count of ftp_start_time and ftp_stop_time when not null) 3. Failed(count of ftp_stop_time must be null).. please help
Screenshot
SELECT
a.Branch_code,
b.DevCount AS total,
COUNT(a.ftp_start_time) AS tried
FROM
ftplogview AS a
LEFT JOIN
palmtecsetup AS b ON a.Branch_code = b.Branch_code
WHERE
ftp_start_date = '2016-03-31'
GROUP BY
a.Branch_code, b.DevCount
ORDER BY
Branch_code
This is the query I used so far ...can anyone help me out?
Hope this one will help you, use the sub select query like below -
SELECT
q.Branch_code,
q.DevCount AS total,
COUNT(q.ftp_start_time) AS tried,
SUM(Success) AS SuccessCount,
SUM(Failed) AS FailedCount,
SUM(NOTTRIED) AS NOTTRIEDCount
FROM
(
SELECT
a.Branch_code,
b.DevCount AS total,
a.ftp_start_time AS tried,
CASE WHEN a.ftp_start_time IS NOT NULL AND a.ftp_stop_time IS NOT NULL THEN 1 ELSE 0 END AS Success,
CASE WHEN a.ftp_start_time IS NOT NULL AND a.ftp_stop_time IS NULL THEN 1 ELSE 0 END AS Failed,
CASE WHEN a.ftp_start_time IS NULL AND a.ftp_stop_time IS NULL THEN 1 ELSE 0 END AS NOTTRIED
FROM
ftplogview AS a
LEFT JOIN
palmtecsetup AS b ON a.Branch_code = b.Branch_code
WHERE
ftp_start_date = '2016-03-31'
) Q
GROUP BY
Q.Branch_code, Q.Total
ORDER BY
Q.Branch_code
I would use Common table expression
with cte(Branch_code, DevCount, total,ftp_start_time,ftp_stop_date,ftp_stop_time )
as (
SELECT
a.Branch_code,
b.DevCount,
a.ftp_start_time,
a.ftp_stop_date,
a.ftp_stop_time
FROM
ftplogview AS a
LEFT JOIN
palmtecsetup AS b ON a.Branch_code = b.Branch_code
GROUP BY
a.Branch_code, b.DevCount
)
SELECT Branch_code,
DevCount AS total,
COUNT(ftp_start_time) AS tried,
SUM(
case
when ftp_start_time is not null and ftp_stop_time is not null then 1
else 0 end
) as success,
SUM(
case
when ftp_stop_time is null then 1
else 0 end
) as failed
FROM CTE
WHERE ftp_start_time = '2016-03-31'

SQL Server - What's the right query for this purpose?

I have a TABLE that contains, for example:
ID CVG
4 A
4 C
5 B
Each row contains a coverage for a given ID. If the ID does not have a coverage, there will be no row in the table (ex. ID 4 has no coverage B).
From this table I want to write a query like
SELECT ID, A = case (when ??? then 'TRUE' when ??? then 'FALSE'), B = case (...), C = case (...) FROM TABLE
that will give the output
ID A B C
4 TRUE FALSE TRUE
5 FALSE TRUE FALSE
where there is only one row for each ID, and one column for each coverage.
What's a workable query for this? I'm not allowed to change any permanent tables on the server so I'm trying to reach a solution with what I have.
You can use conditional aggregation to get the required result:
SELECT ID,
CASE
WHEN COUNT(CASE WHEN CVG = 'A' THEN 1 END)>=1 THEN 'TRUE'
ELSE 'FALSE'
END AS A,
CASE
WHEN COUNT(CASE WHEN CVG = 'B' THEN 1 END)>=1 THEN 'TRUE'
ELSE 'FALSE'
END AS B,
CASE
WHEN COUNT(CASE WHEN CVG = 'C' THEN 1 END)>=1 THEN 'TRUE'
ELSE 'FALSE'
END AS C,
.... etc
FROM mytable
GROUP BY ID
SQL Fiddle Demo
You could do something like this:
select
ID,
max(case when CVG = 'A' then 'TRUE' else 'FALSE' end),
max(case when CVG = 'B' then 'TRUE' else 'FALSE' end),
max(case when CVG = 'C' then 'TRUE' else 'FALSE' end),
from
table
group by
ID
The case + max will select the true if even one row is found for that ID, otherwise false.
If you want to have it select where
A = case (when ??? then 'TRUE' when ??? then 'FALSE'), B = case (...), C = case (...)
which is what I got from your explenation, what you need to do is
SELECT id, A, B, C FROM TABLE WHERE A = case (when ??? then 'TRUE' when ??? then 'FALSE'), B = case (...), C = case (...)

Resources