Supposed I have some sample data in table_name_a as below:
code val_a val_b remark date
------------------------------------------
1 00001 500 0.1 111 20191108
2 00001 1000 0.2 222 20191109
3 00002 200 0.1 111 20191110
4 00002 400 0.3 222 20191111
5 00001 200 0.2 333 20191112
6 00001 400 0.1 444 20191113
My expected output as below:
code 111_a 111_b 222_a 222_b 333_a ....
--------------------------------------------
1 00001 500 .. .. .. ..
And below SQL query will contain 0 value which covered the correct values, does it possible to query without Else or do nothing?
SELECT code, date,
CASE WHEN t.remark='111' THEN t.val_a ELSE 0 END 111_a,
CASE WHEN t.remark='111' THEN t.val_b ELSE 0 END 111_b,
CASE WHEN t.remark='222' THEN t.val_a ELSE 0 END 222_a,
CASE WHEN t.remark='222' THEN t.val_b ELSE 0 END 222_b,
CASE WHEN t.remark='333' THEN t.val_a ELSE 0 END 333_a,
CASE WHEN t.remark='333' THEN t.val_b ELSE 0 END 333_b,
CASE WHEN t.remark='444' THEN t.val_a ELSE 0 END 444_a,
CASE WHEN t.remark='444' THEN t.val_b ELSE 0 END 444_b,
FROM table_name_a t
You need to use MAX with pivoting logic here, though you are on the right track:
SELECT
code,
MAX(CASE WHEN remark = '111' THEN val_a END) 111_a,
MAX(CASE WHEN remark = '111' THEN val_b END) 111_b,
MAX(CASE WHEN remark = '222' THEN val_a END) 222_a,
MAX(CASE WHEN remark = '222' THEN val_b END) 222_b,
MAX(CASE WHEN remark = '333' THEN val_a END) 333_a,
MAX(CASE WHEN remark = '333' THEN val_b END) 333_b,
MAX(CASE WHEN remark = '444' THEN val_a END) 444_a,
MAX(CASE WHEN remark = '444' THEN val_b END) 444_b
FROM table_name_a
GROUP BY
code;
The logic here works because for each group of records belonging to a single code, we take the maximum value only under certain conditions, in this case for certain values of remark. Should the condition be false, then the CASE expressions would return NULL, which would then be ignored by MAX.
Related
The table that needs to be queried looks like this:
ID
UserID
ProductCodes
1
33
9999
2
456
3051
3
456
9999
4
456
3051
4
33
9999
How would I write a SQL query to find out which users have at least one productCodes = '9999' and also have more than 10 productCodes <> '9999'?
You can use GROUP BY and HAVING:
SELECT
UserID
FROM dbo.YourTable
GROUP BY
UserId
HAVING SUM(CASE WHEN ProductCodes = '9999' THEN 1 ELSE 0 END) >= 1
AND COUNT(DISTINCT ProductCodes) >= 11
;
Use Case or Intersect (case is more performant)
SELECT UserID, SUM (case when ProductCodes='9999' then 1 else 0 end) PC9999
, SUM (case when ProductCodes<>'9999' then 1 else 0 end) PCNot9999
FROM dbo.Users
WHERE ProductCodes='9999'
GROUP BY UserID
HAVING SUM (case when ProductCodes='9999' then 1 else 0 end)>0
AND SUM (case when ProductCodes<>'9999' then 1 else 0 end) >10
I ended up going with this. It allows us to get specific with how many times a '9999' product code has been used in comparison with other codes.
SELECT
UserID
FROM Session_Hst
GROUP BY
UserID
HAVING SUM(CASE WHEN ProductCodes = '9999' THEN 1 ELSE 0 END) >= 1
AND COUNT(CASE WHEN ProductCodes <> '9999' THEN 1 ELSE null END ) >= 10
;
I have a sql server 2012 db with a table with 10 columns
name test1, test2, test3, test4,....
bob yes no null yes
john no yes yes null
I want to get a total of all results from the 'test' fields so i want my results to be
yes = 4
no = 2
null = 2
I have tried using cte, sum, case when but I cant get the results i'm looking for. below is a sample of my sql if anyone could tell me how to go about getting the results i'm looking for.
with cte as
(
SELECT
test1,
sum (case when test1 = 'yes' then 1 else 0 end) as yes,
sum (case when test1= 'no' then 1 else 0 end) as no,
sum (case when test1 is null then 1 else 0 end) as notset
from names
group by Inspection1Type)
select
sum (yes) as 'yes',
sum(no) as 'no'
sum(notset) as 'Not Set'
from cte;
it works for the first column but not for the remaining ones as i'm looking for same value it complains about my aliases being the same
Try this cut&paste approach:
SELECT
sum (case when test1 = 'yes' then 1 else 0 end
+case when test2 = 'yes' then 1 else 0 end
+case when test3 = 'yes' then 1 else 0 end
...
+case when test10 = 'yes' then 1 else 0 end) as yes,
sum (case when test1 = 'no' then 1 else 0 end
+case when test2 = 'no' then 1 else 0 end
+case when test3 = 'no' then 1 else 0 end
...
+case when test10 = 'no' then 1 else 0 end) as no,
sum (case when test1 is null then 1 else 0 end
+case when test2 is null then 1 else 0 end
+case when test3 is null then 1 else 0 end
...
+case when test10 is null then 1 else 0 end) as notset
from names
I like handling this with apply. If you want one row per name:
select n.*, v.*
from names n cross apply
(select sum(case when v.test = 'yes' then 1 else 0 end) as yes,
sum(case when v.test = 'no' then 1 else 0 end) as no,
sum(case when v.test is null then 1 else 0 end) as nulls
from (values (n.test1), (n.test2), . . . (n.test10)) v(test)
) v;
If you want one row for all the data:
select sum(case when v.test = 'yes' then 1 else 0 end) as yes,
sum(case when v.test = 'no' then 1 else 0 end) as no,
sum(case when v.test is null then 1 else 0 end) as nulls
from names n cross apply
(values (n.test1), (n.test2), . . . (n.test10)) v(test);
Having repeating columns in a table is usually a sign of an issue with the data model. Normally, you would want one row per name/test, and that would simplify queries on this data.
Try this:
WITH ABC
as
(
SELECT 'bob' as name, 'yes' as test1, 'no' as test2, null as test3, 'yes' as test4
UNION ALL
SELECT 'john', 'no','yes','yes',null
)
SELECT SUM(CASE WHEN A.result = 'yes' then 1 else 0 end) as [Yes],
SUM(CASE WHEN A.result = 'no' then 1 else 0 end) as [No],
SUM(CASE WHEN A.result is null then 1 else 0 end) as [Null]
FROM
(
SELECT name,result
FROM ABC
CROSS APPLY(VALUES(test1),(test2),(test3),(test4)) --may add up to test10
COLUMNNAMES(result)
) as A
I have a table that looks sort of like this:
CustomerID ItemType
001 'a'
001 'b'
001 'c'
001 'd'
002 'd'
How can I structure a select statement that looks something like this:
CASE WHEN ItemType = 'a' THEN 1 ELSE 0 END as Aexists,
CASE WHEN ItemType = 'b' THEN 1 ELSE 0 END as Bexists,
CASE WHEN ItemType = 'c' THEN 1 ELSE 0 END as Cexists,
CASE WHEN ItemType = 'd' THEN 1 ELSE 0 END as Dexists,
CASE WHEN ItemType = 'e' THEN 1 ELSE 0 END as Eexists,
GROUP BY CustomerID
Where the results would look like this:
CustomerID, Aexists, Bexists, Cexists, Dexists, Eexists
001 1 1 1 1 0
002 0 0 0 1 0
I'm confused on how to tell if the items exist since they are spread over rows; I only want one row returned per customer.
Close enough. Use aggregate function MAX
select
CustomerID,
max(CASE WHEN ItemType = 'a' THEN 1 ELSE 0 END) as Aexists,
max(CASE WHEN ItemType = 'b' THEN 1 ELSE 0 END) as Bexists,
max(CASE WHEN ItemType = 'c' THEN 1 ELSE 0 END) as Cexists,
max(CASE WHEN ItemType = 'd' THEN 1 ELSE 0 END) as Dexists,
max(CASE WHEN ItemType = 'e' THEN 1 ELSE 0 END) as Eexists
from t
GROUP BY CustomerID
I have Plant, Material, Movement type and Date.
My requirement is I want the MAX date in Material and Plant combination, with Movement type condition
First I need MAX date in Material and Plant combination, where Movement type is 602 , if 602 is null then 601, if 601 is null then 102, if 102 is null then 101 if 101 also is null then other Movement types.
For this I used below code in derived table in IDT but I am not able to get the correct results:
SELECT
DISTINCT
Table__1."0PLANT",
Table__1."0MATERIAL",
Max(Table__1."0PSTNG_DATE") as Last_Sales_Date
FROM
"NM1"."PUBLIC"."IZDSO_DMR" Table__1
Where
CASE
WHEN (Table__1."0MOVETYPE"=602) THEN (Table__1."0MOVETYPE"=602)
WHEN (Table__1."0MOVETYPE"=602) IS NULL THEN (Table__1."0MOVETYPE"=601)
ELSE
(Table__1."0MOVETYPE"=601) END
Group By
Table__1."0MATERIAL",
Table__1."0PLANT"
I tried only for 602, 601 Movement types only
Please help me to get the correct result
This is your where clause:
Where (CASE WHEN (Table__1."0MOVETYPE"=602) THEN (Table__1."0MOVETYPE"=602)
WHEN (Table__1."0MOVETYPE"=602) IS NULL THEN (Table__1."0MOVETYPE"=601)
ELSE (Table__1."0MOVETYPE"=601)
END)
This will actually work with some SQL engines, because a comparison is turned into a number. However, I don't think this is what you want. You are looking to prioritize the max() value, based on the 0MoveType column.
SELECT "0PLANT", "0MATERIAL",
(case when sum(case when "0MOVETYPE" = 602 then 1 else 0 end) > 0
then max(case when "0MOVETYPE" = 602 then "0PSTNG_DATE" end)
when sum(case when "0MOVETYPE" = 601 then 1 else 0 end) > 0
then max(case when "0MOVETYPE" = 601 then "0PSTNG_DATE" end)
when sum(case when "0MOVETYPE" = 102 then 1 else 0 end) > 0
then max(case when "0MOVETYPE" = 102 then "0PSTNG_DATE" end)
when sum(case when "0MOVETYPE" = 101 then 1 else 0 end) > 0
then max(case when "0MOVETYPE" = 101 then "0PSTNG_DATE" end)
end) as Last_Sales_Date
\FROM "NM1"."PUBLIC"."IZDSO_DMR" Table__1
Group By "0MATERIAL", "0PLANT";
This returns the last sales date for "602" if any are present. If none are present, then it returns the last sales date of "601". If neither "601" nor "602" are present, then it goes to "102" and so on.
I have a single product table with multiple fields which contain user evaluations of various attributes:
product | attr_1_eval | attr_2_eval | attr_3_eval
ABC | Correct | Incorrect | Null
DEF | Incorrect | Null | Null
XYZ | Undetermined | Null | Incorrect
123 | Null | Undetermined | Correct
456 | Incorrect | Correct | Correct
I need to write a query which totals up those attribute evaluations across all products (where not null):
evaluation | correct | incorrect | undetermined
attr_1 | 1 | 2 | 1
attr_2 | 1 | 1 | 1
attr_3 | 2 | 1 | 0
This SQL gets me part way there:
SELECT
SUM(CASE WHEN attr_1_eval = 'Correct' then 1 else 0 END) AS correct,
SUM(CASE WHEN attr_1_eval = 'Incorrect' then 1 else 0 END) AS incorrect,
SUM(CASE WHEN attr_1_eval = 'Undetermined' then 1 else 0 END) AS undetermined,
SUM(CASE WHEN attr_2_eval = 'Correct' then 1 else 0 END) AS correct,
...
FROM product
But it doesn't group attr_1, attr_2.. by rows with error counts in the columns (as in the desired result set above). I'm using Postgres but help in any flavor of SQL would be most welcome.
Could you do 3 unions?
SELECT
'attr_1' AS evaluation,
SUM(CASE WHEN attr_1_eval = 'Correct' then 1 else 0 END) AS correct,
SUM(CASE WHEN attr_1_eval = 'Incorrect' then 1 else 0 END) AS incorrect,
SUM(CASE WHEN attr_1_eval = 'Undetermined' then 1 else 0 END) AS undetermined
FROM product
UNION
SELECT
'attr_2' AS evaluation,
SUM(CASE WHEN attr_2_eval = 'Correct' then 1 else 0 END) AS correct,
SUM(CASE WHEN attr_2_eval = 'Incorrect' then 1 else 0 END) AS incorrect,
SUM(CASE WHEN attr_2_eval = 'Undetermined' then 1 else 0 END) AS undetermined
FROM product
UNION
SELECT
'attr_3' AS evaluation,
SUM(CASE WHEN attr_3_eval = 'Correct' then 1 else 0 END) AS correct,
SUM(CASE WHEN attr_3_eval = 'Incorrect' then 1 else 0 END) AS incorrect,
SUM(CASE WHEN attr_3_eval = 'Undetermined' then 1 else 0 END) AS undetermined
FROM product
It's not the most elegant/efficient solution probably but it should get what you want
It's a little brute force, and I hate the fact that it scans the table three times, but this does appear to get the desired output. I'm sorry I don't know PostGres, but this should work in Oracle:
select
Attribute_name,
Sum (correct) as Correct,
sum (incorrect) as Incorrect,
sum (undetermined) as Undetermined
from
(
select
'attr_1' as Attribute_Name,
decode (attr_1_eval, 'Correct', 1, 0) as correct,
decode (attr_1_eval, 'Incorrect', 1, 0) as incorrect,
decode (attr_1_eval, 'Undetermined', 1, 0) as undetermined
from product
union all
select
'attr_2',
decode (attr_2_eval, 'Correct', 1, 0),
decode (attr_2_eval, 'Incorrect', 1, 0),
decode (attr_2_eval, 'Undetermined', 1, 0)
from product
union all
select
'attr_3',
decode (attr_3_eval, 'Correct', 1, 0),
decode (attr_3_eval, 'Incorrect', 1, 0),
decode (attr_3_eval, 'Undetermined', 1, 0)
from product
)
group by Attribute_Name