I encountered the following code generated from COGNOS:
CASE
WHEN CASE
WHEN 'FIELD1' LIKE 'VAL1'
THEN 1
WHEN 'FIELD1' LIKE 'VAL2'
THEN 2
WHEN 'FIELD1' LIKE 'VAL3'
THEN 3
ELSE 4
END = 1
THEN 'M'
WHEN CASE
WHEN 'FIELD1' LIKE 'VAL1'
THEN 1
WHEN 'FIELD1' LIKE 'VAL2'
THEN 2
WHEN 'FIELD1' LIKE 'VAL3'
THEN 3
ELSE 4
END = 2
THEN 'Q'
WHEN CASE
WHEN 'FIELD1' LIKE 'VAL1'
THEN 1
WHEN 'FIELD1' LIKE 'VAL2'
THEN 2
WHEN 'FIELD1' LIKE 'VAL3'
THEN 3
ELSE 4
END = 3
THEN 'Y'
ELSE 'T'
END AS 'VAL4'
I cannot determine the significance of the '=' operators following 'END = nn'. In addition, the CASE blocks seem to be duplicates that do not provide distinguishing values.
Simplified further than #SpaceUser7448 this would look like:
SELECT
CASE
WHEN 'FIELD1' LIKE 'VAL1' THEN 'M'
WHEN 'FIELD1' LIKE 'VAL2' THEN 'Q'
WHEN 'FIELD1' LIKE 'VAL3' THEN 'Y'
ELSE 'T'
END AS 'VAL4'
This might be clearer
CASE
WHEN (
CASE
WHEN 'FIELD1' LIKE 'VAL1' THEN 1
WHEN 'FIELD1' LIKE 'VAL2' THEN 2
WHEN 'FIELD1' LIKE 'VAL3' THEN 3
ELSE 4
END
) = 1 THEN 'M'
WHEN (
CASE
WHEN 'FIELD1' LIKE 'VAL1' THEN 1
WHEN 'FIELD1' LIKE 'VAL2' THEN 2
WHEN 'FIELD1' LIKE 'VAL3' THEN 3
ELSE 4
END
) = 2 THEN 'Q'
WHEN (
CASE
WHEN 'FIELD1' LIKE 'VAL1' THEN 1
WHEN 'FIELD1' LIKE 'VAL2' THEN 2
WHEN 'FIELD1' LIKE 'VAL3' THEN 3
ELSE 4
END
) = 3 THEN 'Y'
ELSE 'T'
END AS 'VAL4'
Essentially the outer case has, for each of its 'when' options, another case case statement
So,
if Field1 was 'VAL1' then the result would be 'M'
if Field1 was 'VAL2' then the result would be 'Q'
if Field1 was 'VAL3' then the result would be 'Y'
and if Field1 was anything else it would be 'T'
Related
I have a table ctrlr_err_hist that has the following columns:
visit_id
err_cd
err_name
m1_err_cnt
m2_err_cnt
The possible values for err_cd are 0, 1, 3.
Now I want to write a query to have different errors with same visit_id on the same row. For example if the table has following records:
visit_id err_cd err_name m1_err_cnt
1 0 encoder 500
1 3 breakout 212
2 1 obclose 45
2 3 breakout 143
This table will be joined with a tchn_visit_hist table on visit_id. If there is no data for any of the err_cd, it will be null. The end result would look like this:
visit_id encoder_cnt breakout_cnt obclose_cnt
1 500 212 null
2 null 143 45
I wrote the following query which joins same table three times
select t.visit_id, t.door_id, enc.encoder_cnt, brk.breakout_cnt, ob.ob_close_cnt
from tchn_visit_hist t
left join (
select m1_err_cnt as encoder_cnt, visit_id
from ctrlr_err_hist
where err_cd = '0'
) as enc
on t.visit_id = enc.visit_id
left join (
select m1_err_cnt as breakout_cnt, visit_id
from ctrlr_err_hist
where err_cd = '3'
) as brk
on t.visit_id = brk.visit_id
left join (
select m1_err_cnt as ob_close_cnt, visit_id
from ctrlr_err_hist
where err_cd = '1'
) as ob
on t.visit_id = ob.visit_id
I wonder if there is a better, more efficient way to accomplish this.
demo: db<>fiddle
A simple pivot can be achieved by this way:
SELECT
visit_id,
MIN(m1_err_cnt) FILTER (WHERE err_cd = 0) as encoder_cnt,
MIN(m1_err_cnt) FILTER (WHERE err_cd = 1) as ob_close_cnt,
MIN(m1_err_cnt) FILTER (WHERE err_cd = 3) as breakout_cnt
FROM
ctrlr_err_hist
GROUP BY visit_id
Grouping by visit_id and aggregating the columns your are interested in. The FILTER clause filters the element that should be aggregated. In this case the aggregation is only for one special err_cd.
Notice that you have to use an aggregation function. This is because theoretical you could have two or more rows with (visit_id = 1, err_cd = 0). In that case you have to decide what you want to do with several values (SUM, MIN, MAX, AVG, whatever). Because your example contains distinct rows it doesn't matter.
After that you simply join against your tchn_visit_hist table:
SELECT t.visit_id, t.door_id, c.encoder_cnt, c.breakout_cnt, c.ob_close_cnt
FROM (
SELECT
visit_id,
MIN(m1_err_cnt) FILTER (WHERE err_cd = 0) as encoder_cnt,
MIN(m1_err_cnt) FILTER (WHERE err_cd = 1) as ob_close_cnt,
MIN(m1_err_cnt) FILTER (WHERE err_cd = 3) as breakout_cnt
FROM
ctrlr_err_hist
GROUP BY visit_id
) c
JOIN tchn_visit_hist t
ON (t.visit_id = c.visit_id)
You can make Condition in Join
select
a.visit_id,
max(b.encoder_cnt) as encoder_cnt,
max(b.breakout_cnt) as breakout_cnt,
max(b.ob_close_cnt) as ob_close_cnt
from
tchn_visit_hist a
left join(select
case when err_cd = '0' then m1_err_cnt end as encoder_cnt,
case when err_cd = '3' then m1_err_cnt end as breakout_cnt,
case when err_cd = '1' then m1_err_cnt end as ob_close_cnt,
case when err_cd = '0' then visit_id end as encoder_visit,
case when err_cd = '3' then visit_id end as breakout_visit,
case when err_cd = '1' then visit_id end as ob_close_visit
from
tchn_visit_hist) b on case
when a.err_cd = '0' then a.visit_id = encoder_visit
when a.err_cd = '3' then a.visit_id = breakout_visit
when a.err_cd = '1' then a.visit_id = ob_close_visit
end
group by
a.visit_id
order by
a.visit_id asc
Here the Demo
I have a table that looks like this:
ID Location
1 AAA123
1 AAA133
1 AAA832
1 BBB929
1 BBB420
How can I count and group by the first 3 chars so that the result looks like this:
ID AAA_Count BBB_count
1 3 2
I tried something like this:
select [ID], Location,
case when left(location, 3) = 'AAA' then count(location) end as 'AAA',
case when left(location, 3) = 'BBB' then count(location) end as 'BBB',
from Table
group by [ID], left(location, 3)
Any help is appreciated.
Thanks.
You need
select [ID],
count(case when left(location, 3) = 'AAA' then 1 end) as [AAA],
count(case when left(location, 3) = 'BBB' then 1 end) as [BBB]
from Table
group by [ID]
If you want a row based solution instead of column based solution, you can use:
Select ID, left(location, 3) as Chars, count(1) as Counts
from Table group by ID, left(location, 3);
I need a query based on an exclusive Or statement for this I try using the case but I won't get a result in case of Null...
...
and b.[U_Periode] = CASE
when (b.U_Periode= #period) then #period
when (b.U_Periode is NULL ) then null
end
...
The Case that won't be catched is... if B.U_Status is null and b.U_Periode is null.
If the var Periode match the Value and the U_Status = 0 or 1
the only way getting this working for me was this:
...
and
ISNULL( b.[U_Status],'0') = CASE
when (b.U_Status= '1') then '1'
when (isnull( b.U_Status,'0')= '0') then '0'
end
and
ISNULL (b.[U_Periode],'01.01.1901') = CASE
when (b.U_Periode= #period) then #period
when (ISNULL (b.U_Periode,'01.01.1901') = '01.01.1901' ) then '01.01.1901'
end
are there any other better solutions for this?
Best regards
Oliver
Okay... here is my Problem
Table1
InsID ContractID
1 1
2 1
Table2
ID insid Period Status Count
1 1 null null 100
2 1 30.09.2015 1 500
3 2 null null 100
4 2 30.09.2015 1 500
Case '31.08.2015'
in total Value should be 200
in case of '30.09.2015'
the Value should be 1.000
XOR /OR will do the same in this case.
Value case '31.08.2015' = 200
value Case ' 30.09.2015 = 2200
So this is somesing like a subquery
left join (
[dbo].[Table2]b
inner join [dbo].[Table 3]K on k.DocEntry = b.DocEntry and CAST( k.U_CSetID as int) >0
)
on b.[U_InsID] in(select... but here I should have an if statement...
If there are results matching the Date join this
If not than join the result NULL is matching to periode...
Okay.. here is the complete query
the Table2 with the Date of 31.08.2015 should have one Record that include
B_STATUS = Null and B.Preiode = null and there is no available record with the U_Periode '31.08.2015' and a Staus ...
with a date of 30.09.2015
there is a Record matching U_Period = '30.09.2015' in this case the Record with U_Period=null should not effect the result...
Declare #period as varchar(20)= '31-08-2015 00:00:00'
declare #Customer as Varchar(15)='12345'
declare #Contract as varchar(30) = '123'
declare #test as varchar(1) = null
select SUM(cast(K.U_Count as decimal))as counter, K.U_CounterTyp
from [dbo].[Table1] a
left join (
[dbo].[Table2]b
inner join [dbo].[Table 3]K on k.DocEntry = b.DocEntry and CAST( k.U_CSetID as int) >0
)
on b.[U_InsID]=a.[insID] and b.[U_ObjectType]in ('5','1') and
ISNULL( b.[U_Status],'0') = CASE
when (b.U_Status= '1') then '1'
when (isnull( b.U_Status,'0')= '0') then '0'
end
and
ISNULL (b.[U_Periode],'01.01.1901') = CASE
when (b.U_Periode= #period) then #period
when (ISNULL (b.U_Periode,'01.01.1901') = '01.01.1901' ) then '01.01.1901'
end
where a.[customer] =#Customer and a.[Status]='A' and a.[U_ContrCount]='1'
and a.[manufSN] in(
select c.[ManufSN] from [dbo].[Table4] c
inner join [dbo].[OCTR]d on d.[ContractID] = c.[ContractID]
where c.[ManufSN]=a.[manufSN]
and d.[CstmrCode] = a.[customer] and d.[ContractID]=#Contract
)
group by K.U_CounterTyp
you must use the "^" operand, this is XOR operand in TSQL
expression ^ expression
the expression must return or 0 or 1...
stupid example:
WHERE (name like "stackoverflow") ^ (age > 10)
font: https://msdn.microsoft.com/en-us/library/ms190277(v=sql.105).aspx
Update for your check
WHERE (CONVERT(VARCHAR(10), a.[U_Periode], 104) = '30.08.2015') != (a.U_Periode IS NULL)
Olay here is my funktion that chek either a Date Result is there or not.
The only thing is, that the performance is not the best if I run hundreths of sentences ... foreach record (up to app. 1000) I need to query each subtable... and there are many many records in...
Anyway this is the function
CREATE FUNCTION fn_GetInsCounters(#InsId as Varchar(30), #Date as datetime)
returns datetime
as
begin
declare #count as int = 0
declare #Retruns as Datetime
set #count =
(
select count( b.Docentry)
from [dbo].[Table2]b
where b.U_Insid =#InsID
and b.U_Status <> '2'
and b.[U_ObjectType]in ('5','1')
and b.U_Periode=#Date
)
if(#count>0)
begin
set #Retruns = #date
end
else
begin
set #Retruns = '01.01.1901'
end
return #Retruns
end
if anyone gets a better idea???
Best regards
Oliver
I'm writing a query with some CASE expressions and it outputs helper-data columns which help me determine whether or not a specific action is required. I would like to know if I can somehow use the result of a subquery as the output without having to perform the same query twice (between WHEN (subquery) THEN and as the result after THEN)
The dummy code below describes what I'm after. Can this be done? I'm querying a MS2005 SQL database.
SELECT 'Hello StackOverflow'
,'Thanks for reading this question'
,CASE
WHEN
(
SELECT count(*)
FROM sometable
WHERE condition = 1
AND somethingelse = 'value'
) > 0 THEN
-- run the query again to get the number of rows
(
SELECT count(*)
FROM sometable
WHERE condition = 1
AND somethingelse = 'value'
)
ELSE 0
END
SELECT 'Hello StackOverflow'
,'Thanks for reading this question'
,CASE
WHEN
(
SELECT count(*)
FROM sometable
WHERE condition = 1
AND somethingelse = 'value'
) AS subqry_count > 0 THEN
-- use the subqry_count, which fails... "Incorrect syntax near the keyword 'AS'"
subqry_count
ELSE 0
END
Just use the subquery as the source you are selecting from:
SELECT 'Hello StackOverflow'
,'Thanks for reading this question'
,CASE subqry_count.Cnt
WHEN 0 THEN 0
ELSE subqry_count.Cnt
END
FROM ( SELECT count(*) AS Cnt
FROM sometable
WHERE condition = 1
AND somethingelse = 'value'
) subqry_count
As an aside, if you are just going to return 0 if the output from COUNT is 0, then you don't even need to use a 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...