Aggregate function with case statement - sql

I am trying to use the aggregate function with a CASE statement but I am not getting the syntax right.
I am attaching the sample code with the question on what I am trying to achieve but I get the syntax error.
count(case when weekminus1 = 0 and week0 = 1 then distinct(asin) end) as asin_added,
count(case when weekminus1 = 0 and week0 = 1 then distinct(fnsku) end) as fnsku_added,
Any leads will be helpful.

Yo want to express this as:
count(distinct case when weekminus1 = 0 and week0 = 1 then asin end) as asin_added,
count(distinct case when weekminus1 = 0 and week0 = 1 thenfnsku end) as fnsku_added,

Related

SQL : Count with "==" to check in SQL Server [duplicate]

This question already has answers here:
Conditional Count on a field
(8 answers)
Closed last year.
I'm working with SQL Server and I want to create a view (my_View) which has these columns :
[element_1]
[element_2]
[element_3]
[element_4]
All of them are referring to the same column, named [parent_1], in another table (AT)
[parent_1] can have 4 possible values [value_1], [value_2], [value_3] and [value_4].
What I want is that, using COUNT,
[element_1] is equal to the number of times that [parent_1] is equal to [value_1]
same for [element_2], [element_3] and [element_4] equals to [value_2], [value_3] and [value_4].
Is it possible to use "==" inside the COUNT to see if it checks the criteria?
Something like this:
COUNT (AT.parent_1 == "value_1") AS element_1
COUNT (AT.parent_1 == "value_2") AS element_2
COUNT (AT.parent_1 == "value_3") AS element_3
COUNT (AT.parent_1 == "value_4") AS element_4
Thanks guys
You can use the CASE instruction for that
https://learn.microsoft.com/fr-fr/sql/t-sql/language-elements/case-transact-sql?view=sql-server-ver15
SUM (CASE WHEN AT.parent_1 = 'value_4' THEN 1 ELSE 0 END) as element_4
You can do something like:
SELECT
sum(case when parent_1 = "value_1" then 1 else 0 end) as element_1,
sum(case when parent_1 = "value_2" then 1 else 0 end) as element_2,
sum(case when parent_1 = "value_3" then 1 else 0 end) as element_3,
sum(case when parent_1 = "value_4" then 1 else 0 end) as element_4
FROM table;
create my_view as
select
-- other list of columns,
SUM (CASE WHEN AT.parent_1 = 'value_1' THEN 1 ELSE 0 END) as element_1,
SUM (CASE WHEN AT.parent_1 = 'value_2' THEN 1 ELSE 0 END) as element_2,
SUM (CASE WHEN AT.parent_1 = 'value_3' THEN 1 ELSE 0 END) as element_3,
SUM (CASE WHEN AT.parent_1 = 'value_4' THEN 1 ELSE 0 END) as element_4
from tableName AT
There is no need to use == like that of a programming language, in SQL comparison operator is =

Combining COUNT Queries [duplicate]

This question already has answers here:
How can I get multiple counts with one SQL query?
(12 answers)
Closed 4 years ago.
I am counting specific things in a SQL Server table. I am using multiple count queries, but I am wondering if it's possible to combine them into a single query with the column name and count numbers in a single table for display.
My queries are:
select count(*) as Ask_Count
from Pld_OpenSalesOrdersLines
where left(C_Item_ID, 1) = '*'
select count(*) as M_Count
from Pld_OpenSalesOrdersLines
where (left(C_Item_ID, 1) = 'M' and len(C_Item_ID) = 1)
select count(*) as MN_Count
from Pld_OpenSalesOrdersLines
where (left(C_Item_ID, 2) = 'MN' and len(C_Item_ID) = 2)
I tried a couple stupid things to combine them, but they were a failure. I honestly can't even begin to think how to combine them, maybe it's not possible?
Thanks!
You could use CASE expression to perform conditional aggregation:
select
COUNT(CASE WHEN LEFT(C_Item_ID,1)='*' THEN 1 END) AS Ask_Count,
COUNT(CASE WHEN LEFT(C_Item_ID,1)='M' AND LEN(C_Item_ID)=1 THEN 1 END) M_Count,
COUNT(CASE WHEN LEFT(C_Item_ID,2)='MN' AND LEN(C_Item_ID)=2 THEN 1 END) MN_Count
from Pld_OpenSalesOrdersLines
Use conditional aggregation:
select sum(case when LEFT(C_Item_ID,1) = '*' then 1 else 0 end) as count_1,
sum(case when LEFT(C_Item_ID,1) = 'M' AND LEN(C_Item_ID)=1 then 1 else 0 end) as count_2,
sum(case when LEFT(C_Item_ID,2) = 'MN' AND LEN(C_Item_ID)=2 then 1 else 0 end) as count_3
from Pld_OpenSalesOrdersLines;
I would write the logic like this, though:
select sum(case when C_Item_ID like '*%' then 1 else 0 end) as count_1,
sum(case when C_Item_ID = 'M' then 1 else 0 end) as count_2,
sum(case when C_Item_ID = 'MN' then 1 else 0 end) as count_3
from Pld_OpenSalesOrdersLines;
Doing a left() on a column and then checking the length is redundant. Just use =.

Trying to get count of votes in SQL based on ID

Table structures:
Solution_Votes:
ID int
SolutionID string
Vote int
Solution:
ID int
Solution
VotesUp
VotesDown
Code:
SELECT
*,
(SELECT SUM(CASE WHEN voteUp = 1 THEN 1 ELSE 0 END)
FROM Solutions_Votes) AS VoteCountUp,
(SELECT SUM(CASE WHEN voteDown = 0 THEN 1 ELSE 0 END)
FROM Solutions_Votes) AS VoteCountDown
FROM
Solution
When I run this query it gives me the count on each row for voteUpCount and voteDownCount. I need the count to be based on the solution ID so that each solution has its count of up votes and down votes. If anybody can help it would be appreciated. Thanks in advance!
Just use conditional aggregation. In your case this is simple:
select sv.solutionid,
sum(case when sv.voteUp = 1 then 1 else 0 end) as VoteCountUp,
sum(case when sv.voteDown = 0 then 1 else 0 end) as VoteCountDown
from solutions_votes sv
group by sv.solutionid;
You only need the solutions table if some solutions have no votes and you want to include them.
EDIT:
You would include solutions in various way. Here is one:
select s.*, ss.VoteCountUp, ss.VoteCountDown
from solutions s left join
(select sv.solutionid,
sum(case when sv.voteUp = 1 then 1 else 0 end) as VoteCountUp,
sum(case when sv.voteDown = 0 then 1 else 0 end) as VoteCountDown
from solutions_votes sv
group by sv.solutionid
) ss
on s.solutionid = ss.solutionid;

Remove duplicate rows when using CASE WHEN statement

I am currently generating a table which converts the rows value to the new column, the following is my code:
SELECT ref_no,
(CASE WHEN code = 1 THEN code END) AS 'count_1',
(CASE WHEN code = 2 THEN code END) AS 'count_2',
(CASE WHEN code = 3 THEN code END) AS 'count_3',
(CASE WHEN code = 4 THEN code END) AS 'count_4',
(CASE WHEN code = 5 THEN code END) AS 'count_5',
(CASE WHEN code = 6 THEN code END) AS 'count_6'
FROM data"
The output is:
However, I needs those duplicated rows to be combined, is there any way to do? I don't need to sum up those values as there is no overlap among them.
I've tried with group by but it does not work as expected:
My expected out put is like:
ref c_1 c_2 c_3 c_4 c_5 c_6
1 1 2 3 - - -
This shows adding ORDER BY clause does not work in my context.
Updated: complete query in sqldf
The answer is: YES
By using GROUP BY and MAX like this:
SELECT ref_no,
max(CASE WHEN code = 1 THEN code END) AS 'count_1',
max(CASE WHEN code = 2 THEN code END) AS 'count_2',
max(CASE WHEN code = 3 THEN code END) AS 'count_3',
max(CASE WHEN code = 4 THEN code END) AS 'count_4',
max(CASE WHEN code = 5 THEN code END) AS 'count_5',
max(CASE WHEN code = 6 THEN code END) AS 'count_6'
FROM data
GROUP BY ref_no
ORDER BY ref_no
You could use PIVOT for this
SELECT *
FROM (
SELECT ref_no, code FROM data
) data
PIVOT (
max(code) FOR code IN ([1], [2], [3], [4], [5], [6])
) pivoted
The easiest would either be to use GROUP BY or a PIVOT function.
GROUP BY example below:
SELECT ref_no,
sum(CASE WHEN code = 1 THEN code ELSE 0 END) AS 'count_1',
sum(CASE WHEN code = 2 THEN code ELSE 0 END) AS 'count_2',
sum(CASE WHEN code = 3 THEN code ELSE 0 END) AS 'count_3',
sum(CASE WHEN code = 4 THEN code ELSE 0 END) AS 'count_4',
sum(CASE WHEN code = 5 THEN code ELSE 0 END) AS 'count_5',
sum(CASE WHEN code = 6 THEN code ELSE 0 END) AS 'count_6'
FROM data
GROUP BY ref_no
A really long way of doing this using your existing code and a CTE table:
WITH results as (
SELECT ref_no,
(CASE WHEN code = 1 THEN code END) AS 'count_1',
(CASE WHEN code = 2 THEN code END) AS 'count_2',
(CASE WHEN code = 3 THEN code END) AS 'count_3',
(CASE WHEN code = 4 THEN code END) AS 'count_4',
(CASE WHEN code = 5 THEN code END) AS 'count_5',
(CASE WHEN code = 6 THEN code END) AS 'count_6'
FROM data)
SELECT
ref_no
, sum(coalesce(count_1),0) -- for sum
, max(coalesce(count_1),0) -- for just the highest value
-- Repeat for other ones
FROM
results
GROUP BY
ref_no

case statement doesn't go to else

I am wondering why the following query doesn't give 'N/A' when there are no rows for ENVIRON='Dev/Int'. It is returning null in the result of the query. I tried doing NVL(COUNT(*)) but that does't work either.
Any thoughts?
Thanks in advance.
SELECT G1.NAME,
(SELECT CASE
WHEN COUNT(*) > 0 AND ticket IS NOT NULL THEN 'Solved'
WHEN COUNT(*) > 0 AND ticket IS NULL THEN 'Done'
ELSE 'N/A'
END
FROM TABLE1
WHERE ENVIRON='Dev/Int' AND G1.NAME=NAME GROUP BY ENVIRON, ticket ) "Dev/Int"
FROM TABLE1 G1 group by G1.NAME
It doesn't give any rows because you are filtering them all out. The case is inside the query. When there are no rows to process, it returns NULL.
I think you just want conditional aggregation. The subqueries don't seem necessary:
SELECT G1.NAME,
(CASE WHEN SUM(CASE WHEN ENVIRON = 'Dev/Int' then 1 else 0 END) > 0 AND ticket IS NOT NULL
THEN 'Solved'
WHEN SUM(CASE WHEN ENVIRON = 'Dev/Int' then 1 else 0 END) > 0 AND ticket IS NULL
THEN 'Done'
ELSE 'N/A'
END) as "Dev/Int"
FROM TABLE1
group by G1.NAME;
EDIT:
Oops, the above left ticket out of the sum(). I think the logic you want has ticket in the sum() condition:
SELECT G1.NAME,
(CASE WHEN SUM(CASE WHEN ENVIRON = 'Dev/Int' AND ticket IS NOT NULL then 1 else 0 END) > 0
THEN 'Solved'
WHEN SUM(CASE WHEN ENVIRON = 'Dev/Int' AND ticket IS NULL then 1 else 0 END) > 0
THEN 'Done'
ELSE 'N/A'
END) as "Dev/Int"
FROM TABLE1
group by G1.NAME;
I'm surprised your original query worked at all and didn't get an error of the sort that subquery returned more than one row.