SQL Sum Case when State equals - sql

I'm looking for SQL coding that will sum the count when a certain state appears and have that sum for the state's particular row. I was able to create two columns to sum the count for a specific state but then that number is in every row.
For example, if there are 24 Arizona records then I went 24 to appear in every row for Arizona. And if there are 58 Oregon records then I want 58 to appear in every row for Oregon. And so on...
This is what I currently have
select appid, rcvddt, state,
sum(count(case when state = 'OR' then 1 else null end)) over () as ORcount,
sum(count(case when state = 'AZ' then 1 else null end)) over () as AZcount
from smbus.submissions
where (apprcvddt >= '2017-08-01' and apprcvddt <= '2018-08-31')
group by state, rcvddt, appid
order by (case when state is null then 1 else 0 end), state

I think you just want count() as a window function:
select s.*,
count(*) over (partition by state) as state_cnt
from smbus.submissions s
where apprcvddt >= '2017-08-01' and apprcvddt <= '2018-08-31'
order by (case when state is null then 1 else 0 end), state

Related

SQL query select returns different result than expected

I'm querying on this 2 tables:
TIMBRATURE
ASSELEMGEN
This is my query:
select convert(varchar(11),convert(date,datav),105) as data,
sum (CASE WHEN idterminale=3 and DATEPART(hour,datav)>='9' and DATEPART(hour,datav)<='16' THEN 1 ELSE 0 END) as pranzoP,
sum (CASE WHEN idterminale=3 and DATEPART(hour,datav)>='17' and DATEPART(hour,datav)<='23' THEN 1 ELSE 0 END) as cenaP,
sum (CASE WHEN idterminale=3 THEN 1 ELSE 0 END) as totaleP
from TIMBRATURE where DATAV>=#dataDa and DATAV<#primoGGmeseSuccessivo and TIMBRATURE.IDDIP
in (select iddip from ASSELEMGEN where IDELEM=1001)
group by convert(date,datav)
order by convert(date,datav)
For this purpose consider this argumets:
declare #datada as date='20230201'
declare #primoggmesesuccessivo as date='20230207'
The result I get:
Iddip is user ID, problem is when user have 2 entries for the same day, one with datav hour part between 9 and 16, the other between 17 and 23. In this case I have to count 2 for it, but my query only count it once. For example in the result above on 1th February I expect PranzoP=93 and totaleP=130.

How I can group by and count in PostgreSQL to prevent empty cells in result

I have the table in PostgreSQL DB
Need to calculate SUM of counts for each event_type (example for 4 and 1)
When I use query like this
SELECT account_id, date,
CASE
WHEN event_type = 1 THEN SUM(count)
ELSE null
END AS shows,
CASE
WHEN event_type = 4 THEN SUM(count)
ELSE null
END AS clicks
FROM widgetstatdaily WHERE account_id = 272 AND event_type = 1 OR event_type = 4 GROUP BY account_id, date, event_type ORDER BY date
I receive this table
With <null> fields. It's because I have event_type in select and I need to GROUP BY on it.
How I can make query to receive grouped by account_id and date result without null's in cells? Like (first row)
272 2018-03-28 00:00:00.000000 57 2
May be I can group it after receiving result
You need conditional aggregation and some other fixes. Try this:
SELECT account_id, date,
SUM(CASE WHEN event_type = 1 THEN count END) as shows,
SUM(CASE WHEN event_type = 4 THEN count END) as clicks
FROM widgetstatdaily
WHERE account_id = 272 AND
event_type IN (1, 4)
GROUP BY account_id, date
ORDER BY date;
Notes:
The CASE expression should be an argument to the SUM().
The ELSE NULL is redundant. The default without an ELSE is NULL.
The logic in the WHERE clause is probably not what you intend. That is fixed using IN.
try its
SELECT account_id, date,
SUM(CASE WHEN event_type = 1 THEN count else 0 END) as shows,
SUM(CASE WHEN event_type = 4 THEN count else 0 END) as clicks
FROM widgetstatdaily
WHERE account_id = 272 AND
event_type IN (1, 4)
GROUP BY account_id, date
ORDER BY date;

Multiple Condition with Groupby

I am getting error wih following code, "Msg 144, Level 15, State 1, Line 17
Cannot use an aggregate or a subquery in an expression used for the group by list of a GROUP BY clause.
"
SELECT [sddoc],
[Soldtopt],
[tradingname],
[DlvDate],
SUM(try_cast(Netvalue AS FLOAT)) AS Netvalue,
COUNT(DISTINCT SDDoc) AS Salesdoc ,
COUNT(DISTINCT
CASE
WHEN Netvalue = '0'
THEN 1
ELSE NULL
END) AS ZeroValue ,
COUNT(DISTINCT SDDoc) - COUNT(DISTINCT
CASE
WHEN Netvalue = '0'
THEN 1
ELSE NULL
END) AS Result
FROM d1
WHERE dlvdate='25.01.2017'
GROUP BY
CASE
WHEN SUM(try_cast(Netvalue AS FLOAT)) = 0
AND COUNT(DISTINCT SDDoc) = 1
AND COUNT(DISTINCT
CASE
WHEN Netvalue = '0'
THEN 1
ELSE NULL
END) = 1
THEN [sddoc]
END,
Soldtopt,
tradingname,
DlvDate
You can't use SUM or COUNT (aggregates) in the GROUP BY clause. Aggregate values must be calculated after groups are defined.
Also, your CASE lacks an ELSE clause.

Returning rows when flag field occurs on same Day

I have a flag field that returns either '0' or '1'. I want to return rows when both a '0' and a '1' occur on the same day. My sytax is off but you get what I mean.
select employee, date, flag, account,
from table1
where flag = 0 and 1 for date
You can aggregate by date and count the number of occurrences of each value:
select employee, date, account,
from table1
group by date, employee, account
having sum(case when flag = 0 then 1 else 0 end) > 0 and
sum(case when flag = 1 then 1 else 0 end) > 0;
In your case, assuming the flag is a number that only takes on the values of 0 and 1, you could simplify it to one of the following:
having count(distinct flag) = 2;
having min(flag) <> max(flag);
having sum(flag) > 0 and sum(1 - flag) > 0;

SQL sum of column value, unique per user per day

I have a postgres table that looks like this:
id | user_id | state | created_at
The state can be any of the following:
new, paying, paid, completing, complete, payment_failed, completion_failed
I need a statement that returns a report with the following:
sum of all paid states by date
sum of all completed states by date
sum of all new, paying, completing states by date with only one per user per day to be counted
sum of all payment_failed, completion_failed by date with only one per user per day to be counted
So far I have this:
SELECT
DATE(created_at) AS date,
SUM(CASE WHEN state = 'complete' THEN 1 ELSE 0 END) AS complete,
SUM(CASE WHEN state = 'paid' THEN 1 ELSE 0 END) AS paid
FROM orders
WHERE created_at BETWEEN ? AND ?
GROUP BY DATE(created_at)
A sum of the in progress and failed states is easy enough by adding this to the select:
SUM(CASE WHEN state IN('new','paying','completing') THEN 1 ELSE 0 END) AS in_progress,
SUM(CASE WHEN state IN('payment_failed','completion_failed') THEN 1 ELSE 0 END) AS failed
But i'm having trouble figuring out how to make only one per user_id per day in_progress and failed states to be counted.
The reason I need this is to manipulate the failure rate in our stats, as many users who trigger a failure or incomplete order go on to trigger more which inflates our failure rate.
Thanking you in advance.
SELECT created_at::date AS the_date
,SUM(CASE WHEN state = 'complete' THEN 1 ELSE 0 END) AS complete
,SUM(CASE WHEN state = 'paid' THEN 1 ELSE 0 END) AS paid
,COUNT(DISTINCT CASE WHEN state IN('new','paying','completing')
THEN user_id ELSE NULL END) AS in_progress
,COUNT(DISTINCT CASE WHEN state IN('payment_failed','completion_failed')
THEN user_id ELSE NULL END) AS failed
FROM orders
WHERE created_at BETWEEN ? AND ?
GROUP BY created_at::date
I use the_date as alias, since it is unwise (while allowed) to use the key word date as identifier.
You could use a similar technique for complete and paid, one is as good as the other there:
COUNT(CASE WHEN state = 'complete' THEN 1 ELSE NULL END) AS complete
Try something like:
SELECT
DATE(created_at) AS date,
SUM(CASE WHEN state = 'complete' THEN 1 ELSE 0 END) AS complete,
SUM(CASE WHEN state = 'paid' THEN 1 ELSE 0 END) AS paid,
COUNT(DISTINCT CASE WHEN state IN('new','paying','completing') THEN user_id ELSE NULL END) AS in_progress,
COUNT(DISTINCT CASE WHEN state IN('payment_failed','completion_failed') THEN user_id ELSE NULL END) AS failed
FROM orders
WHERE created_at BETWEEN ? AND ?
GROUP BY DATE(created_at);
The main idea - COUNT (DISTINCT ...) will count unique user_id and wont count NULL values.
Details: aggregate functions, 4.2.7. Aggregate Expressions
The whole query with same style counts and simplified CASE WHEN ...:
SELECT
DATE(created_at) AS date,
COUNT(CASE WHEN state = 'complete' THEN 1 END) AS complete,
COUNT(CASE WHEN state = 'paid' THEN 1 END) AS paid,
COUNT(DISTINCT CASE WHEN state IN('new','paying','completing') THEN user_id END) AS in_progress,
COUNT(DISTINCT CASE WHEN state IN('payment_failed','completion_failed') THEN user_id END) AS failed
FROM orders
WHERE created_at BETWEEN ? AND ?
GROUP BY DATE(created_at);