Sum in case expression - sql

I am writing a code in SQL Server 2017 Windows 10. I don't know where the issue is and I can't get the result of total in case expression.
Here is my code
select PD.PONO, PM.CURRSTATUS, PD.Qty
, case when pm.currstatus = 1 then sum(pd.qty) end TotalStock
from ppom PM
LEFT OUTER join ppod PD on pd.pono = pm.pono
where pm.pono = 15973
group by PD.PONO, PM.CURRSTATUS, PD.Qty
GO
Result is showing below
PONO CURRSTATUS Qty TotalStock
15973 1 8 8
15973 1 14 14
15973 1 25 25
While result should show the sum value
PONO CURRSTATUS Qty TotalStock
15973 1 8 47
15973 1 14 47
15973 1 25 47
Please help me in this thanks

You seem to want a window sum rather than aggregation. It would look like:
select
pd.pono,
pm.currstatus,
pd.qty,
sum(case when pm.currstatus = 1 then pd.qty else 0 end)
over(partition by pd.pono) total_stock
from ppom pm
left join ppod pd on pd.pono = pm.pono

Related

SUM the COUNT results from a database table with two different value

I'd like to count total events, which can have two different values, and I could not figure out how to merge them together. My query is the following:
SELECT TOP(20)
[MatchEvents].[PlayerID], [MatchEvents].[EventType],
COUNT([MatchEvents].[ID]) AS [TOTAL]
FROM
[MatchEvents]
INNER JOIN
[Match] ON [MatchEvents].[MatchID] = [Match].[ID]
AND [Match].[Season] = 1
WHERE
([MatchEvents].[EventType] = 0 OR [MatchEvents].[EventType] = 1)
GROUP BY
[MatchEvents].[PlayerID], [MatchEvents].[EventType]
ORDER BY
[TOTAL] ESC
Current output:
PlayerID
EventType
Total
1
0
8
1
1
3
2
0
8
2
1
3
3
0
8
3
1
3
Expected output:
PlayerID
Total
1
11
2
11
3
11
How could I merge my current results further?
Thanks!
From your expected results it appears you just need to remove grouping by EventType
I would suggest the following:
select top(20) me.PlayerID, Count(*) as Total
from MatchEvents me
join [Match] m on m.Id = me.MatchId and m.Season = 1
where me.EventType in (0, 1)
group by me.PlayerID
order by Total desc;

SQL query to find those customer who have buy all three items ('ring','diamond','brooch')

id item_name cust_id
1 Rolex 5
2 Diamond 33
3 Hublop 1
4 Ring 9
5 Ruby 13
6 Rolex 33
7 Hublop 29
8 Ring 17
9 Belt 21
10 Diamond 9
12 Belt 33
13 Hublop 9
14 Brooch 9
From these table I have to write a query to find those cust_id who have buy all three 'diamond,brooch,ring'
without using intersection ( IN clause will also not work)
You can use sum with a case statement for each item to get how many of that item the client has bought, then filter only customers that have bought at least one of each type of product:
select cust_id from
(select cust_id,
sum(case when item_name = 'Diamond' then 1 else 0 end) as cntDiamond,
sum(case when item_name = 'Brooch' then 1 else 0 end) as cntBrooch,
sum(case when item_name = 'Ring' then 1 else 0 end) as cntRing
from table_name
group by cust_id) as t
where cntDiamond > 0 and cntBrooch > 0 and cntRing > 0
Fiddle

Get datetime difference group by query results in one row

I have a table Master_History with structure as
Id_History Created_Date Subscription_Type rn
21 1/22/2016 16:31:29 1 1
22 1/22/2016 16:33:11 2 2
23 1/22/2016 16:33:37 1 3
24 1/22/2016 16:33:46 2 4
25 1/22/2016 16:33:53 1 5
26 1/22/2016 16:33:57 3 6
27 1/22/2016 16:34:01 2 7
28 1/22/2016 16:34:04 1 8
29 1/22/2016 16:34:08 3 9
I want to calculate date difference with adjacent rows which i have succeeded in calculating but results are getting distributed over multiple rows
Standard Plus Premium
122 NULL NULL
NULL 35 NULL
NULL NULL 3
I need
Results in one row like
Standard Plus Premium
122 35 3
For the last row (in this Subscription_Type is 3, the date difference should also get calculated on getdate() i.e. whenever i executed my query, seconds in Premium column should get reflected each time
Query :
WITH CTE
AS (
SELECT *
,ROW_NUMBER() OVER (
ORDER BY Created_Date
) AS rn
FROM Master_History
WHERE Client_ID = 11072
)
SELECT CASE
WHEN mc.Subscription_Type = 1
THEN Sum(DATEDIFF(second, mc.Created_Date, mp.Created_Date))
END AS [Standard]
,CASE
WHEN mc.Subscription_Type = 2
THEN Sum(DATEDIFF(second, mc.Created_Date, mp.Created_Date))
END AS Plus
,CASE
WHEN mc.Subscription_Type = 3
THEN Sum(DATEDIFF(second, mc.Created_Date, mp.Created_Date))
END AS Premium
FROM CTE mc
JOIN CTE mp ON mc.rn = mp.rn - 1
GROUP BY mc.Subscription_Type
try this
select
count(Standard.*) Standard_,
count(Plus.*) Plus_,
count(Premium.*) Premium_
from
Master_History master_
left outer join Master_History Standard on Standard.Subscription_Type = 1
and master_.Subscription_Type = Standard.Subscription_Type
left outer join Master_History Plus on Plus.Subscription_Type = 2
and master_.Subscription_Type = Plus.Subscription_Type
left outer join Master_History Premium on Premium.Subscription_Type = 3
and master_.Subscription_Type = Plus.Subscription_Type
where
convert(date,master_.Created_Date) < convert(date,getdate()) and
convert(date,master_.Created_Date) < convert(date,Standard.Created_Date) and
convert(date,master_.Created_Date) < convert(date,Plus.Created_Date) and
convert(date,master_.Created_Date) < convert(date,Premium.Created_Date)

SQL - Get Sum of Values with same Date

I'm sure I've done this type of operation a 1000 times before but for some reason this is not working for me. I'm doing a report to determine if a patient receive medication on a day. So regardless if they get 1 does or 5 doses in a day the value should be 1. Staff also do corrections on the system, that come in as negative values. So I need to sum all of the dose value for each day, if it is a + value then its 1, otherwise its a 0.
All i want to accomplish at this point is to have 1 row for each date as either 1 or 0.
Here is my SQL Query to sum the values:
SELECT
DIM_DRUG_NAME_SHORT.Drug_Name_Short AS 'Med_Name_Short'
, SUM(Baseline.Doses) as 'DOT'
, Day(Baseline.Dispense_Date) as 'd_Date'
FROM
FACT_AMS_Baseline_Report Baseline
INNER JOIN DIM_DRUG_NAME_SHORT ON Baseline.Med_Name_ID = DIM_DRUG_NAME_SHORT.Drug_Name_Long
INNER JOIN DIM_Date tDate ON Baseline.Dispense_Date = tDate.Date
WHERE
Baseline.Encounter = '00000001/01'
GROUP BY
DIM_DRUG_NAME_SHORT.Drug_Name_Short
, Baseline.Dispense_Date
, Doses
Order By
Drug_Name_Short
For time being I'm just pulling one encounter out of the data set to test with.
This is the output i'm getting. I also included the Day in the select just to show that the same day is coming through twice and they are not getting Summed.
Here is a sample of the output I get:
Med_Name_Short DOT day of month
CEFTRIAXONE 1 15
CEFTRIAXONE 1 16
CEFTRIAXONE 4 16
CEFTRIAXONE 1 17
CEFTRIAXONE 1 18
CEFTRIAXONE 1 20
CEFTRIAXONE -3 21
CEFTRIAXONE 1 21
CEFTRIAXONE -1 23
PROPRANOLOL -1 24
PROPRANOLOL 3 24
PROPRANOLOL 1 25
PROPRANOLOL 2 26
PROPRANOLOL 2 27
What I was hoping to see in this was that Day 16 would be a 5, day 21 would be -2 and day 24 would be -2.
Any assistance would be greatly appreciated.
Thanks
Remove Doses from your Group By list. You are using an aggregate function on it (SUM) which is correct, so it should not be in the GROUP BY.
I don't think you should be grouping by doses. Without seeing your data, I can only guess that, for example, there are two doses of quantity 2 on the 16th.
So try:
SELECT
DIM_DRUG_NAME_SHORT.Drug_Name_Short AS 'Med_Name_Short'
, SUM(Baseline.Doses) as 'DOT'
, Day(Baseline.Dispense_Date) as 'd_Date'
FROM
FACT_AMS_Baseline_Report Baseline
INNER JOIN DIM_DRUG_NAME_SHORT ON Baseline.Med_Name_ID = DIM_DRUG_NAME_SHORT.Drug_Name_Long
INNER JOIN DIM_Date tDate ON Baseline.Dispense_Date = tDate.Date
WHERE
Baseline.Encounter = '00000001/01'
GROUP BY
DIM_DRUG_NAME_SHORT.Drug_Name_Short
, Baseline.Dispense_Date
Order By
Drug_Name_Short
Since you're aggregating on doses you should remove it from the group by, and to get either 1 or 0 for doses use a case expression:
SELECT
DIM_DRUG_NAME_SHORT.Drug_Name_Short AS 'Med_Name_Short'
, CASE WHEN SUM(Baseline.Doses) >= 1 THEN 1 ELSE 0 END AS 'DOT'
, Day(Baseline.Dispense_Date) as 'd_Date'
FROM
FACT_AMS_Baseline_Report Baseline
INNER JOIN DIM_DRUG_NAME_SHORT ON Baseline.Med_Name_ID = DIM_DRUG_NAME_SHORT.Drug_Name_Long
INNER JOIN DIM_Date tDate ON Baseline.Dispense_Date = tDate.Date
WHERE
Baseline.Encounter = '00000001/01'
GROUP BY
DIM_DRUG_NAME_SHORT.Drug_Name_Short
, Baseline.Dispense_Date
Order By
Drug_Name_Short
If the dispense_date is a datetime value you should probably use Day(Baseline.Dispense_Date) in the group by or remove the time part.
If you group by day and your data spans over more than one month you should either limit the range or include year and month as well so that data from different months/years don't get summed up.
With your sample data you should get a result like:
Med_Name_Short DOT day of month
CEFTRIAXONE 1 15
CEFTRIAXONE 1 16
CEFTRIAXONE 1 17
CEFTRIAXONE 1 18
CEFTRIAXONE 1 20
CEFTRIAXONE 0 21
CEFTRIAXONE 0 23
PROPRANOLOL 1 24
PROPRANOLOL 1 25
PROPRANOLOL 1 26
PROPRANOLOL 1 27

How to fill in the gaps in a query of totals with zeroes?

I have a table with data like this
picks
20
20
20
18
17
12
12
9
9
This is the table but I need to get result like this.
Picks Count
20 3
19 0
18 1
17 1
16 0
...up to
1 12
How can we write query to get zero totals for data which doesn't exist in the table?
Arun
Use a subquery to generate all the numbers and then outer join it to your table.
with nos as ( select level as pick_id
from dual
connect by level <= 20 )
select nos.pick_id
, count(*)
from nos
left outer join picks
on nos.pick_id = picks.id
group by nos.pick_id
order by nos.pick_id desc ;