Sum by Distinct Values - sql

I have the below code which brings though a sum of where a day 'GRLastDt' has complete or not complete however I hadn't accounted for duplicated Return IDs. Is there a way to return a sum by day for each Return ID?
For example day 24/5/15 may have 5 Lines to the day which have 'X' in Complete however 2 lines have duplicated return ids 'RtnId' and therefore the sum total would be 4 rather than 5 for 24/5/15.
SELECT
CONVERT(varchar(15), GRLastDt, 111) AS Date_,
SUM(CASE WHEN Complete = 'X' THEN 1 ELSE 0 END) AS Complete,
SUM(CASE WHEN Complete <> 'X' /*and RtnDt <>GRLastDt*/THEN 1 ELSE 0 END) AS Due
FROM [dbo].[vw_AN_Admin_VendorReturns]
WHERE (GRLastDt >= GETDATE() - 30)
GROUP BY CONVERT(varchar(15), GRLastDt, 111),GRLastDt

If I understand your problem right I think you can change this line:
SUM(CASE WHEN Complete = 'X' THEN 1 ELSE 0 END) AS Complete,
to this:
COUNT(DISTINCT CASE WHEN Complete = 'X' THEN RtnId END) AS Complete,
You probably want the same change for the Due calculation.

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.

SQL case operation

Im fairly new with sql, and been trying to solve a problem where you have a table information about orders. In this case, Im trying to use the case operation to get a monthly report on orders, so I should have a column which states the year,another one which states the month, and then I should have columns for days 1-20,21-22,23-24 and above 25. Im trying to use the case operation to get the amount of orders that happened on those days.
I tried the following query :
SELECT
DATEPART(YEAR,date) AS year,DATEPART(MONTH,date) AS month,
COUNT(CASE WHEN DATEPART(DAY,date) BETWEEN 1 AND 20 THEN order ELSE 0 END) AS D1_D20,
COUNT(CASE WHEN DATEPART(DAY,date) BETWEEN 21 AND 22 THEN order ELSE 0 END) AS D21_D22,
COUNT(CASE WHEN DATEPART(DAY,date) BETWEEN 23 AND 24 THEN order ELSE 0 END) AS D23_D24,
COUNT(CASE WHEN DATEPART(DAY,date) > 25 THEN order ELSE 0 END) AS D25_END
FROM ORDERS
GROUP BY DATEPART(YEAR,date),DATEPART(MONTH,date)
Obviously the problem with that query is that, now I just get the total number of orders for each of the days, I know I should count the orders, but dont know the syntax. Help would be greatly appreciated!
Use SUM():
SELECT
DATEPART(YEAR, date) AS year, DATEPART(MONTH, date) AS month,
SUM(CASE WHEN DATEPART(DAY,date) BETWEEN 1 AND 20 THEN 1 ELSE 0 END) AS D1_D20,
SUM(CASE WHEN DATEPART(DAY,date) BETWEEN 21 AND 22 THEN 1 ELSE 0 END) AS D21_D22,
SUM(CASE WHEN DATEPART(DAY,date) BETWEEN 23 AND 24 THEN 1 ELSE 0 END) AS D23_D24,
SUM(CASE WHEN DATEPART(DAY,date) > 25 THEN 1 ELSE 0 END) AS D25_END
FROM ORDERS
GROUP BY DATEPART(YEAR, date), DATEPART(MONTH, date);
I would recommend using the functions DAY(), YEAR(), and MONTH() because they are simpler to type.
By the way, you can use COUNT() if you remove the ELSE clause. Your particular problem is that COUNT(0) = COUNT(1) because COUNT() counts non-NULL values. I prefer SUM() because it is more intuitive in this respect.

SQL using SUM in CASE in SUM

I had this query select
sum(CASE WHEN kpi.average >= temp.average THEN 1 ELSE 0 END) AS recordOrder,
which worked fine, but I had to change it to this
sum(CASE WHEN sum(kpi.averageUse) / sum(kpi.averageTotal) >= temp.average THEN 1 ELSE 0 END) AS recordOrder,
These queries have to get number of rows, where some value (average) is greater than average from TEMP table. But in the second query I have more accurate data (weighted average).
but I am getting error
1111 invalid use of group function
Any ideas how to write SUM in CASE in SUM?
Thanks!
This code is just non-sensical because you have nested sum functions:
sum(CASE WHEN sum(kpi.averageUse) / sum(kpi.averageTotal) >= temp.average THEN 1 ELSE 0 END) AS recordOrder,
Without seeing your larger query, it is not possible to know what you really intend. But I would speculate that you don't want the internal sum()s:
sum(CASE WHEN (skpi.averageUse / kpi.averageTotal) >= temp.average THEN 1 ELSE 0 END) AS recordOrder,

SQL percentage with rows same table with different where condition

I want to do a query like:
select
count(asterisk) where acción='a'/count(asterisk) where acción='b' * 100
from
same_table
grouped by day
but I don't want use subquery, is it possible with joins?
I`m not sure the syntax is correct, but you can use something like this:
SELECT day,
SUM(CASE WHEN "acción" = 'a' THEN 1 ELSE 0 END) AS SUM_A,
SUM(CASE WHEN "acción" = 'b' THEN 1 ELSE 0 END) AS SUM_B,
SUM(CASE WHEN "acción" = 'a' THEN 1 ELSE 0 END) AS SUM_A / SUM(CASE WHEN "acción" = 'b' THEN 1 ELSE 0 END) * 100 AS result
FROM your_table
GROUP BY day
The concept is to actually sum the the values that you need, instead of count.

Dynamically Creating Column Counts Per Day of Month

OK, so I have this query to find number of types per day like below. (Courtesy of MarkD here Counting Items/Rows in DB as Columns Grouped by Another Column)
select type,
sum(case when MyDate = '' then 1 else 0 end) as "10/1",
sum(case when MyDate = '' then 1 else 0 end) as "10/2
...etc
from MyTabe
group by type
However, I want to dynamically create date columns and have the count generated for each column, otherwise I would end up manually adding a new column for each day of the month.
I guess the best way to get the output I wanted was to do the following:
define startDate = to_date('2013-10-01', 'yyyy-mm-dd')
select type,
sum(case when MyDate = &&startDate then 1 else 0 end) as "1"
, sum(case when MyDate = &&startDate +1 then 1 else 0 end) as "2"
, sum(case when MyDate = &&startDate +2 then 1 else 0 end) as "3"
, sum(case when MyDate = &&startDate +3 then 1 else 0 end) as "4"
...etc for as many days of current month I am running
, sum(case when MyDate = &&startDate +29 then 1 else 0 end) as "30"
, sum(case when MyDate = &&startDate +30 then 1 else 0 end) as "31"--This would be commented out for Nov
from MyTabe
group by type
order by type
;
This way if I want to run this for Nov, Dec, Jan, and so on, I can just change the variable at the top and run the query. This is what I was looking for; however, I still wonder if it would be possible to generate the columns dynamically, but the more I look at it, the more I think that would require a pivot table.