Query inside CASE statement with SUM - sql-server

I have a nestled query I need to use in my CASE statement. I need to use the Max(AgeDate) that is correctly retrieved in the SELECT statement in my CASE statement but it does not see my Max(AgeDate) in my SELECT statement in my CASE statement. Please help...
Select
Inv.InvoiceNumber,
Fact_FinInvoice.InvoiceID,
dbo.Dim_Date.FullDate AS InvoiceDate,
pra.PracticeName,
pra.PracticeLogonName,
pat.AccNo,
pat.FileNo,
pmai.MedicalAidNumber,
per.Title + ' ' + per.Initials + ' ' + per.Surname AS PatientName,
sch.SCHEMES5,
sch.SchemeOption,
(SELECT MAX(B.AgeDate) FROM Fact_FinInvoice B WHERE Fact_FinInvoice.InvoiceID = B.InvoiceID AND Fact_FinInvoice.PracticeIdKey = B.PracticeIdKey) MaxAgeDate,
SUM(Fact_FinInvoice.Amount) AS Amount,
SUM(Fact_FinInvoice.AmountFunder) AS AmountFunder,
SUM(Fact_FinInvoice.AmountPatient) AS AmountPatient,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 0 and 29 and AmountFunder != 0 THEN AmountFunder ELSE 0 END) as FunderCurrent,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 30 and 59 and AmountFunder != 0 THEN AmountFunder ELSE 0 END) as Funder30Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 60 and 89 and AmountFunder != 0 THEN AmountFunder ELSE 0 END) as Funder60Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 90 and 119 and AmountFunder != 0 THEN AmountFunder ELSE 0 END) as Funder90Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) >= 120 and AmountFunder != 0 THEN AmountFunder ELSE 0 END) as Funder120Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 0 and 29 and AmountPatient != 0 THEN AmountPatient ELSE 0 END) as PatientCurrent,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 30 and 59 and AmountPatient != 0 THEN AmountPatient ELSE 0 END) as Patient30Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 60 and 89 and AmountPatient != 0 THEN AmountPatient ELSE 0 END) as Patient60Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 90 and 119 and AmountPatient != 0 THEN AmountPatient ELSE 0 END) as Patient90Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) >= 120 and AmountPatient != 0 THEN AmountPatient ELSE 0 END) as Patient120Days,
mcs.Name AS BureauManager,
mcso.Name AS BureauOfficer
FROM dbo.Fact_FinInvoice LEFT OUTER JOIN
dbo.Dim_Practice pra ON dbo.Fact_FinInvoice.PracticeIdKey = pra.PracticeIDCode LEFT OUTER JOIN
dbo.Fact_Invoice Inv ON dbo.Fact_FinInvoice.InvoiceID = Inv.ID LEFT OUTER JOIN
dbo.Dim_PersonMAInfo pmai INNER JOIN
dbo.Dim_Scheme sch ON sch.CodeNo = pmai.CodeNo ON Inv.PersonMAInfoCode = pmai.PersonMAInfoID LEFT OUTER JOIN
dbo.Dim_BureauStaffProvider bsp INNER JOIN
dbo.Dim_MediChargeStaff mcs ON mcs.ID = bsp.BureauStaffId ON bsp.ProviderID = Inv.ProviderId INNER JOIN
dbo.Dim_MediChargeStaff mcso ON mcs.Manager = mcso.ID LEFT OUTER JOIN
dbo.Dim_Date ON Inv.InvoiceDateKey = dbo.Dim_Date.DateKey LEFT OUTER JOIN
dbo.Dim_Patient pat INNER JOIN
dbo.Dim_PersonData per ON per.PersonDataId = pat.PersonId ON pat.PatientId = Inv.PatientKey
GROUP BY Inv.InvoiceNumber,
Fact_FinInvoice.InvoiceID,
dbo.Dim_Date.FullDate,
pra.PracticeName,
pra.PracticeLogonName,
pmai.MedicalAidNumber,
sch.SCHEMES5,
sch.SchemeOption,
mcs.Name,
mcso.Name,
pat.AccNo,
pat.FileNo,
per.Title + ' ' + per.Initials + ' ' + per.Surname,
[Fact_FinInvoice].PracticeIdKey

USE CTE on top and then join that CTE with your joins:
;with mycte as (
select MAX(AgeDate) as MaxAgeDate,InvoiceID FROM Fact_FinInvoice
group by InvoiceID
)
Select
Inv.InvoiceNumber,
Fact_FinInvoice.InvoiceID,
dbo.Dim_Date.FullDate AS InvoiceDate,
pra.PracticeName,
pra.PracticeLogonName,
pat.AccNo,
pat.FileNo,
pmai.MedicalAidNumber,
per.Title + ' ' + per.Initials + ' ' + per.Surname AS PatientName,
sch.SCHEMES5,
sch.SchemeOption,
MaxAgeDate,
SUM(Fact_FinInvoice.Amount) AS Amount,
SUM(Fact_FinInvoice.AmountFunder) AS AmountFunder,
SUM(Fact_FinInvoice.AmountPatient) AS AmountPatient,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 0 and 29 and AmountFunder != 0 THEN AmountFunder ELSE 0 END) as FunderCurrent,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 30 and 59 and AmountFunder != 0 THEN AmountFunder ELSE 0 END) as Funder30Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 60 and 89 and AmountFunder != 0 THEN AmountFunder ELSE 0 END) as Funder60Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 90 and 119 and AmountFunder != 0 THEN AmountFunder ELSE 0 END) as Funder90Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) >= 120 and AmountFunder != 0 THEN AmountFunder ELSE 0 END) as Funder120Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 0 and 29 and AmountPatient != 0 THEN AmountPatient ELSE 0 END) as PatientCurrent,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 30 and 59 and AmountPatient != 0 THEN AmountPatient ELSE 0 END) as Patient30Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 60 and 89 and AmountPatient != 0 THEN AmountPatient ELSE 0 END) as Patient60Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 90 and 119 and AmountPatient != 0 THEN AmountPatient ELSE 0 END) as Patient90Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) >= 120 and AmountPatient != 0 THEN AmountPatient ELSE 0 END) as Patient120Days,
mcs.Name AS BureauManager,
mcso.Name AS BureauOfficer
FROM dbo.Fact_FinInvoice LEFT OUTER JOIN
dbo.Dim_Practice pra ON dbo.Fact_FinInvoice.PracticeIdKey = pra.PracticeIDCode LEFT OUTER JOIN
dbo.Fact_Invoice Inv ON dbo.Fact_FinInvoice.InvoiceID = Inv.ID LEFT OUTER JOIN
dbo.Dim_PersonMAInfo pmai INNER JOIN
dbo.Dim_Scheme sch ON sch.CodeNo = pmai.CodeNo ON Inv.PersonMAInfoCode = pmai.PersonMAInfoID LEFT OUTER JOIN
dbo.Dim_BureauStaffProvider bsp INNER JOIN
dbo.Dim_MediChargeStaff mcs ON mcs.ID = bsp.BureauStaffId ON bsp.ProviderID = Inv.ProviderId INNER JOIN
dbo.Dim_MediChargeStaff mcso ON mcs.Manager = mcso.ID LEFT OUTER JOIN
dbo.Dim_Date ON Inv.InvoiceDateKey = dbo.Dim_Date.DateKey LEFT OUTER JOIN
dbo.Dim_Patient pat INNER JOIN
dbo.Dim_PersonData per ON per.PersonDataId = pat.PersonId ON pat.PatientId = Inv.PatientKey
join mycte ct
on Fact_FinInvoice.InvoiceID = ct.InvoiceID
GROUP BY Inv.InvoiceNumber,
Fact_FinInvoice.InvoiceID,
dbo.Dim_Date.FullDate,
pra.PracticeName,
pra.PracticeLogonName,
pmai.MedicalAidNumber,
sch.SCHEMES5,
sch.SchemeOption,
mcs.Name,
mcso.Name,
pat.AccNo,
pat.FileNo,
per.Title + ' ' + per.Initials + ' ' + per.Surname,
[Fact_FinInvoice].PracticeIdKey

You can't use aliases given in select part in other places in the select, but you can use outer apply to fetch data that you'll then use in select, with something like this:
select
....
sch.SchemeOption,
AD.MaxAgeDate,
....
SUM(CASE WHEN DATEDIFF(dd, AD.MaxAgeDate, GETDATE())
from
dbo.Fact_FinInvoice
outer apply (
SELECT MAX(B.AgeDate)
FROM Fact_FinInvoice B
WHERE Fact_FinInvoice.InvoiceID = B.InvoiceID AND
Fact_FinInvoice.PracticeIdKey = B.PracticeIdKey) AD
LEFT OUTER JOIN ...
And you can also calculate the datediff already in the outer apply as a second column, so you don't have to repeat the same code several times.

Use Cross Apply
SELECT Inv.InvoiceNumber,
Fact_FinInvoice.InvoiceID,
dbo.Dim_Date.FullDate AS InvoiceDate,
pra.PracticeName,
pra.PracticeLogonName,
pat.AccNo,
pat.FileNo,
pmai.MedicalAidNumber,
per.Title + ' ' + per.Initials + ' ' + per.Surname AS PatientName,
sch.SCHEMES5,
sch.SchemeOption,
cs.MaxAgeDate,
Sum(Fact_FinInvoice.Amount) AS Amount,
Sum(Fact_FinInvoice.AmountFunder) AS AmountFunder,
Sum(Fact_FinInvoice.AmountPatient) AS AmountPatient,
Sum(CASE
WHEN Datediff(dd, MaxAgeDate, Getdate()) BETWEEN 0 AND 29
AND AmountFunder != 0 THEN AmountFunder
ELSE 0
END) AS FunderCurrent,
Sum(CASE
WHEN Datediff(dd, MaxAgeDate, Getdate()) BETWEEN 30 AND 59
AND AmountFunder != 0 THEN AmountFunder
ELSE 0
END) AS Funder30Days,
Sum(CASE
WHEN Datediff(dd, MaxAgeDate, Getdate()) BETWEEN 60 AND 89
AND AmountFunder != 0 THEN AmountFunder
ELSE 0
END) AS Funder60Days,
Sum(CASE
WHEN Datediff(dd, MaxAgeDate, Getdate()) BETWEEN 90 AND 119
AND AmountFunder != 0 THEN AmountFunder
ELSE 0
END) AS Funder90Days,
Sum(CASE
WHEN Datediff(dd, MaxAgeDate, Getdate()) >= 120
AND AmountFunder != 0 THEN AmountFunder
ELSE 0
END) AS Funder120Days,
Sum(CASE
WHEN Datediff(dd, MaxAgeDate, Getdate()) BETWEEN 0 AND 29
AND AmountPatient != 0 THEN AmountPatient
ELSE 0
END) AS PatientCurrent,
Sum(CASE
WHEN Datediff(dd, MaxAgeDate, Getdate()) BETWEEN 30 AND 59
AND AmountPatient != 0 THEN AmountPatient
ELSE 0
END) AS Patient30Days,
Sum(CASE
WHEN Datediff(dd, MaxAgeDate, Getdate()) BETWEEN 60 AND 89
AND AmountPatient != 0 THEN AmountPatient
ELSE 0
END) AS Patient60Days,
Sum(CASE
WHEN Datediff(dd, MaxAgeDate, Getdate()) BETWEEN 90 AND 119
AND AmountPatient != 0 THEN AmountPatient
ELSE 0
END) AS Patient90Days,
Sum(CASE
WHEN Datediff(dd, MaxAgeDate, Getdate()) >= 120
AND AmountPatient != 0 THEN AmountPatient
ELSE 0
END) AS Patient120Days,
mcs.Name AS BureauManager,
mcso.Name AS BureauOfficer
FROM dbo.Fact_FinInvoice FFI
LEFT OUTER JOIN dbo.Dim_Practice pra ON FFI.PracticeIdKey = pra.PracticeIDCode
LEFT OUTER JOIN dbo.Fact_Invoice Inv ON FFI.InvoiceID = Inv.ID
LEFT OUTER JOIN dbo.Dim_PersonMAInfo pmai
INNER JOIN dbo.Dim_Scheme sch ON sch.CodeNo = pmai.CodeNo ON Inv.PersonMAInfoCode = pmai.PersonMAInfoID
LEFT OUTER JOIN dbo.Dim_BureauStaffProvider bsp
INNER JOIN dbo.Dim_MediChargeStaff mcs ON mcs.ID = bsp.BureauStaffId ON bsp.ProviderID = Inv.ProviderId
INNER JOIN dbo.Dim_MediChargeStaff mcso ON mcs.Manager = mcso.ID
LEFT OUTER JOIN dbo.Dim_Date ON Inv.InvoiceDateKey = dbo.Dim_Date.DateKey
LEFT OUTER JOIN dbo.Dim_Patient pat
INNER JOIN dbo.Dim_PersonData per ON per.PersonDataId = pat.PersonId ON pat.PatientId = Inv.PatientKey
CROSS APPLY (SELECT Max(B.AgeDate) AS MaxAgeDAte
FROM Fact_FinInvoice B
WHERE FFI.InvoiceID = B.InvoiceID
AND FFI.PracticeIdKey = B.PracticeIdKey) CS
GROUP BY Inv.InvoiceNumber,
FFI.InvoiceID,
dbo.Dim_Date.FullDate,
pra.PracticeName,
pra.PracticeLogonName,
pmai.MedicalAidNumber,
sch.SCHEMES5,
sch.SchemeOption,
mcs.Name,
mcso.Name,
pat.AccNo,
pat.FileNo,
per.Title + ' ' + per.Initials + ' ' + per.Surname,
[FFI].PracticeIdKey

Related

Creating Ageing report (>0), (0-30), (31-60)

I am trying to write an Ageing Report on SQL Server which shows the total amount of overdue invoices (later on I will have to deduct Credit Notes) that fall in the different columns depending on how many days the have been overdued. I.e (>0), (0-30), (31-60), (61-90), etc.
This is the part of the query I have written so far mostly looking at old post in this forum but it's giving me a lot of duplicates even for Accounts where there is not due balance.
Any idea what I am doing wrong?
SELECT O.cardcode AS [Account],
O.cardname AS [Name],
O.u_creditlimit AS [Credit Limit],
O.u_onhold AS [On Hold],
O.balance,
Isnull(CASE
WHEN Datediff(day, INV.docduedate, Getdate()) >= 0 AND Datediff(day, INV.docduedate, Getdate()) < 30
THEN (
SELECT Sum(doctotal)
FROM oinv
WHERE cardcode = INV.cardcode)
END, 0) AS [0 to 30 Days],
Isnull(CASE
WHEN Datediff(day, INV.docduedate, Getdate()) >= 31 AND Datediff(day, INV.docduedate, Getdate()) < 60
THEN (
SELECT Sum(doctotal)
FROM oinv
WHERE cardcode = INV.cardcode)
END, 0) AS [31 to 60 Days],
Isnull(CASE
WHEN Datediff(day, INV.docduedate, Getdate()) >= 61 AND Datediff(day, INV.docduedate, Getdate()) < 90
THEN (
SELECT Sum(doctotal)
FROM oinv
WHERE cardcode = INV.cardcode)
END, 0) AS [61 to 90 Days],
Isnull(CASE
WHEN Datediff(day, INV.docduedate, Getdate()) >= 91 AND Datediff(day, INV.docduedate, Getdate()) < 120
THEN (
SELECT Sum(doctotal)
FROM oinv
WHERE cardcode = INV.cardcode)
END, 0) AS [91 to 120 Days],
Isnull(CASE
WHEN Datediff(day, INV.docduedate, Getdate()) >= 121
THEN(
SELECT Sum(doctotal)
FROM oinv
WHERE cardcode = INV.cardcode)
END, 0) AS [121+ Days]
FROM ocrd O
INNER JOIN oinv INV
ON O.cardcode = INV.cardcode
WHERE territory = 3
AND INV.docstatus = 'O'
Thank you very much.
You can clean this up a bit
First. use a CROSS APPLY to calculate the Days-Past-Due once, and then a conditional aggregation for the final results
Example (Untested)
Select O.cardcode
,O.cardname
,[Credit Limit] = max(O.u_creditlimit)
,[On Hold] = max(O.u_onhold)
,[0 to 30 Days] = sum( case when DPD between 0 and 30 then doctotal else 0 end)
,[31 to 60 Days] = sum( case when DPD between 31 and 60 then doctotal else 0 end)
,[61 to 90 Days] = sum( case when DPD between 61 and 90 then doctotal else 0 end)
,[91 to 120 Days] = sum( case when DPD between 91 and 120 then doctotal else 0 end)
,[121+ Days ] = sum( case when DPD >=121 then doctotal else 0 end)
From ocrd O
Join oinv INV on O.cardcode = INV.cardcode
Cross Apply (values ( Datediff(day, INV.docduedate, Getdate()) ) ) P(DPD)
Where territory = 3
and INV.docstatus = 'O'
and DPD >= 0
Group By O.cardcode
,O.cardname
EDIT - CREDIT NOTES
Without sample data or structures here is my GUESS
Select O.cardcode
,O.cardname
,[Credit Limit] = max(O.u_creditlimit)
,[On Hold] = max(O.u_onhold)
,[0 to 30 Days] = sum( case when DPD between 0 and 30 then doctotal - isnull(creditnotes,0) else 0 end)
,[31 to 60 Days] = sum( case when DPD between 31 and 60 then doctotal - isnull(creditnotes,0) else 0 end)
,[61 to 90 Days] = sum( case when DPD between 61 and 90 then doctotal - isnull(creditnotes,0) else 0 end)
,[91 to 120 Days] = sum( case when DPD between 91 and 120 then doctotal - isnull(creditnotes,0) else 0 end)
,[121+ Days ] = sum( case when DPD >=121 then doctotal - isnull(creditnotes,0) else 0 end)
From ocrd O
Join oinv INV on O.cardcode = INV.cardcode
LEFT JOIN CREDITNOTESTable CN ON O.cardcode = CN.cardcode
Cross Apply (values ( Datediff(day, INV.docduedate, Getdate()) ) ) P(DPD)
Where territory = 3
and INV.docstatus = 'O'
and DPD >= 0
Group By O.cardcode
,O.cardname
when asking questions is a great idea to provide demo data, and a better one to provide it as an object we can easily re recreate:
DECLARE #table TABLE (RecordID INT IDENTITY, CardCode INT, CardName NVARCHAR(100), u_CreditLimit DECIMAL(10,2), u_onhold DECIMAL(10,2), balance DECIMAL(10,2))
INSERT INTO #table (CardCode, CardName, u_CreditLimit, u_onhold, balance) VALUES (1, 'John Smith', 10000, 0, 200),
(1, 'John Smith', 10000, 0, 400),
(1, 'John Smith', 10000, 0, 200)
This would allow someone to just run the TSQL to create and populate the object.
Now using that object we could write something like
SELECT RecordID, CardCode, CardName, U_CreditLimit, U_OnHold, Balance, COALESCE(LAG(Balance,1) OVER (PARTITION BY CardCode ORDER BY RecordID) - Balance,Balance) AS RunningTotal
FROM #table
This psudeo code, and may need some tweaking to get exactly what you're looking for.
A quick word on LAG and its pal LEAD. You specify a column and an offset in rows. LAG looks backwards, LEAD forwards. They both use over clauses just like any other windowed function.

How can separate morning and evening shifts patients with gender wise using SQL stored procedure

I want to separate the morning and evening patient checked-in count gender-wise and also if gender age less then show the Female child and M child on the basis of gender.
SELECT
COUNT(ch.EnteredOn) AS counter,
CONVERT(date, ch.EnteredOn) AS sessionDay,
SUM(CASE WHEN CAST(CONVERT(CHAR(2), ch.EnteredOn, 108) AS INT) < 12 THEN 1 ELSE 0 END) AS 'Morning',
SUM(CASE WHEN CAST(CONVERT(CHAR(2), ch.EnteredOn, 108) AS INT) >= 12 THEN 1 ELSE 0 END) AS 'Evening',
SUM(CASE WHEN p.Gender = 1 THEN 1 ELSE 0 END) AS Male,
SUM(CASE WHEN p.Gender = 2 THEN 1 ELSE 0 END) AS Fmale,
SUM(CASE WHEN DATEDIFF(hour, P.DOB, GETDATE()) / 8766 <= 18
AND P.Gender = 1 THEN 1 ELSE 0 END) AS MChild,
SUM(CASE WHEN DATEDIFF(hour, P.DOB, GETDATE()) / 8766 <= 18
AND P.Gender = 2 THEN 1 ELSE 0 END) AS FChild
FROM
Patient.CheckIn ch
INNER JOIN
Patient.Patients P ON ch.PatientId = p.PatientId
GROUP BY
Ch.EnteredOn
I have only three columns like Gender, Time and DOB. Gender id 1 shows the male and Gender id 2 is using for females.
enter image description here
SELECT convert(date, ch.EnteredOn) AS sessionDay, CAST( CONVERT(CHAR(2), ch.EnteredOn, 108) AS INT) <12 as morning, count(ch.EnteredOn) AS counter
,sum(case when p.Gender=1 Then 1 ELSE 0 end) as Male
,sum(case when p.Gender=2 Then 1 ELSE 0 end) as Fmale
,Sum( case when DATEDIFF(hour,P.DOB,GETDATE())/8766<=18 AND P.Gender=1 Then 1 ELSE 0 end ) as MChiled
,Sum( case when DATEDIFF(hour,P.DOB,GETDATE())/8766<=18 AND P.Gender=2 Then 1 ELSE 0 end ) as FChiled
FROM Patient.CheckIn ch
inner join Patient.Patients P on ch.PatientId=p.PatientId
Group by Ch.EnteredOn
Group BY can be
Group by convert(date, ch.EnteredOn) AS sessionDay, CAST( CONVERT(CHAR(2), ch.EnteredOn, 108) AS INT) <12

Aging report 30,60,90 above

I try to count the no. of bills received between 30,60 and above 90 days.
Here is my T-SQL query:
SELECT
costcentreid,
'Current' = CASE
WHEN DATEDIFF(DAY, BillDate, Getdate()) < 30
THEN COUNT(PVNo)
END,
'30_days' = CASE
WHEN DATEDIFF(DAY, BillDate, Getdate()) BETWEEN 30 AND 60
THEN COUNT(PVNo)
END,
'60_days' = CASE
WHEN DATEDIFF(DAY, BillDate, Getdate()) BETWEEN 60 AND 90
THEN COUNT(PVNo)
END,
'90_plus' = CASE
WHEN DATEDIFF(DAY, BillDate, Getdate()) > 90
THEN COUNT(PVNo)
END
FROM
SPRGMMS..PVRegister
GROUP BY
CostCentreId
When I run this, I get an error:
Msg 8120, Level 16, State 1, Line 2
Column '[DB]..PVRegister.BillDate' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Kindly help
You need the aggregation outside
SELECT
costcentreid,
COUNT(CASE
WHEN DATEDIFF(DAY, BillDate, Getdate()) < 30
THEN PVNo
END) as 'Current',
COUNT(CASE
WHEN DATEDIFF(DAY, BillDate, Getdate()) BETWEEN 30 AND 60
THEN PVNo
END) as '30_days',
COUNT(CASE
WHEN DATEDIFF(DAY, BillDate, Getdate()) BETWEEN 60 AND 90
THEN PVNo
END) as '60_days',
COUNT(CASE
WHEN DATEDIFF(DAY, BillDate, Getdate()) > 90
THEN PVNo
END) as '90_plus'
FROM
SPRGMMS..PVRegister
GROUP BY CostCentreId
SELECT
costcentreid,
SUM(CASE WHEN d = 1 THEN 1 ELSE 0 END) AS '30_days'
SUM(CASE WHEN d = 2 THEN 1 ELSE 0 END) AS '60_days',
SUM(CASE WHEN d = 3 THEN 1 ELSE 0 END) AS '90_days',
FROM (
SELECT PVNo, costcentreid, DATEDIFF(DAY, BillDate, Getdate())) / 30 AS d FROM SPRGMMS..PVRegister
) T
WHERE d <= 3
GROUP BY costcentreid

unpivot one row of aggregates to 1 column

I have this query that returns 1 row of aggregate sums
DECLARE #Income9 int
SELECT #Income9 = IncomeLevel FROM PovertyLevels WHERE HouseholdNumber = 9
;WITH CTE
AS
(
SELECT PatientProfileID, CASE WHEN v.FamilyMembersinHousehold > 8
THEN ROUND((CAST(AnnualIncome as float)/(CAST(#Income9 as float) +((V.FamilyMembersinHousehold-8)* CAST(#Income9 as Float)))*100.00), 5)
WHEN ((v.FamilyMembersinHousehold IS NULL) OR (AnnualIncome IS NULL)) THEN NULL
ELSE ROUND(((CAST(AnnualIncome AS Float)/CAST(pl.IncomeLevel as Float)) * 100.00), 5) END AS PercentOfPoverty
FROM vPatientDemographics v
LEFT OUTER JOIN PovertyLevels pl ON v.FamilyMembersinHousehold = pl.HouseholdNumber
)
SELECT SUM(CASE WHEN PercentOfPoverty <= 100 THEN 1 ELSE 0 END) AS NumOfPatientsBelow100,
SUM(CASE WHEN PercentOfPoverty BETWEEN 101 AND 150 THEN 1 ELSE 0 END) AS NumOfPatientsBetween101And150,
SUM(CASE WHEN PercentOfPoverty BETWEEN 151 AND 200 THEN 1 ELSE 0 END) AS NumOfPatientsBetween151And200,
SUM(CASE WHEN PercentOfPoverty > 200 THEN 1 ELSE 0 END) AS NumOfPatientsOver200,
SUM(CASE WHEN PercentOfPoverty IS NULL THEN 1 ELSE 0 END) AS NumOfPatientsUnknown
FROM CTE
I would like to have the sum data to be in rows not columns.
I tried adding this UNPIVOT but it does not recognize the column names.
UNPIVOT
(
Levels for PovertyLevels in (NumOfPatientsBelow100, NumOfPatientsBetween101And150, NumOfPatientsBetween151And200,
NumOfPatientsOver200, NumOfPatientsUnknown)
) as Unpvt
How can I unpivot the initial data set to that it is in rows not columns?
It is because Where clause is evaluated before the select
SELECT #Income9 = IncomeLevel FROM PovertyLevels WHERE HouseholdNumber = 9
;WITH CTE
AS
(
SELECT PatientProfileID, CASE WHEN v.FamilyMembersinHousehold > 8
THEN ROUND((CAST(AnnualIncome as float)/(CAST(#Income9 as float) +((V.FamilyMembersinHousehold-8)* CAST(#Income9 as Float)))*100.00), 5)
WHEN ((v.FamilyMembersinHousehold IS NULL) OR (AnnualIncome IS NULL)) THEN NULL
ELSE ROUND(((CAST(AnnualIncome AS Float)/CAST(pl.IncomeLevel as Float)) * 100.00), 5) END AS PercentOfPoverty
FROM vPatientDemographics v
LEFT OUTER JOIN PovertyLevels pl ON v.FamilyMembersinHousehold = pl.HouseholdNumber
),intr as
(
SELECT SUM(CASE WHEN PercentOfPoverty <= 100 THEN 1 ELSE 0 END) AS NumOfPatientsBelow100,
SUM(CASE WHEN PercentOfPoverty BETWEEN 101 AND 150 THEN 1 ELSE 0 END) AS NumOfPatientsBetween101And150,
SUM(CASE WHEN PercentOfPoverty BETWEEN 151 AND 200 THEN 1 ELSE 0 END) AS NumOfPatientsBetween151And200,
SUM(CASE WHEN PercentOfPoverty > 200 THEN 1 ELSE 0 END) AS NumOfPatientsOver200,
SUM(CASE WHEN PercentOfPoverty IS NULL THEN 1 ELSE 0 END) AS NumOfPatientsUnknown
FROM CTE
)
Select cnt,range from intr
cross apply (values (NumOfPatientsBelow100,'NumOfPatientsBelow100'),
(NumOfPatientsBetween101And150,'NumOfPatientsBetween101And150'),
(NumOfPatientsBetween151And200,'NumOfPatientsBetween151And200'),
(NumOfPatientsOver200,'NumOfPatientsOver200'),
(NumOfPatientsUnknown,'NumOfPatientsUnknown')) cs (cnt,range)

Grouping Records by header SQL

I have the following query;
SELECT STOCK_CODE,
dbo.manu_STOCK.DESCRIPTION,
QTY_IN_STOCK,
Quantity,
ForecastDate
FROM [FS25-w2k8\SQLEXPRESS].sagel50_46772.dbo.SalesForecastLines AS SalesForecastLines1
INNER JOIN dbo.manu_STOCK
ON SalesForecastLines1.ProductCode = dbo.manu_STOCK.STOCK_CODE
This brings up the following information;
STOCK_CODE DESCRIPTION QTY_INSTOCK Quantity ForecastDate
523 gel 12 10 01/08/2014
523 gel 12 10 08/08/2014
I want to be able to modify the query so that it displays the following formation
Stock Code Description WK1 WK2
523 gel 22 22
So it will sum qty in stock and quantity on the first date and the column will be called wk1, second week - wk2 etc.
Can you advise on this please?
IF you want to pivot the results for 52 weeks, you can use the following query. This will pivot data for 52 weeks. This is just concept, I could not test this query.
SELECT * FROM
( SELECT
dbo.manu_STOCK.STOCK_CODE AS [Stock Code],
dbo.manu_STOCK.DESCRIPTION,
DATEPART(WEEK,[Date]) Wk,
QTY_IN_STOCK + Quantity AS Stock
FROM [FS25-w2k8\SQLEXPRESS].sagel50_46772.dbo.SalesForecastLines AS SalesForecastLines1
INNER JOIN dbo.manu_STOCK
ON SalesForecastLines1.ProductCode = dbo.manu_STOCK.STOCK_CODE
) AS Source
PIVOT
(
SUM(Stock)
FOR WK IN
([0],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10]
,[11],[12],[13],[14],[15],[16],[17],[18],[19],[20]
,[21],[22],[23],[24],[25],[26],[27],[28],[29],[30]
,[31],[32],[33],[34],[35],[36],[37],[38],[39],[40]
,[41],[42],[43],[44],[45],[46],[47],[48],[49],[50]
,[51],[52])
) AS PVT ;
DECLARE #Stock TABLE
(
STOCK_CODE INT,
DESCRIPTION VARCHAR(50),
QTY_INSTOCK INT,
QUANTITY INT,
FORECASTDATE DATETIME
)
INSERT INTO #Stock
( STOCK_CODE, DESCRIPTION, QTY_INSTOCK, QUANTITY, FORECASTDATE )
VALUES
( 523, 'gel', 12, 10, '01/08/2014' ),
( 523, 'gel', 12, 10, '08/08/2014' )
SELECT
s.STOCK_CODE,
s.DESCRIPTION,
s.STOCKYEAR,
SUM(CASE WHEN s.STOCKWEEK = 1 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk1,
SUM(CASE WHEN s.STOCKWEEK = 2 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk2,
SUM(CASE WHEN s.STOCKWEEK = 3 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk3,
SUM(CASE WHEN s.STOCKWEEK = 4 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk4,
SUM(CASE WHEN s.STOCKWEEK = 5 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk5,
SUM(CASE WHEN s.STOCKWEEK = 6 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk6,
SUM(CASE WHEN s.STOCKWEEK = 7 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk7,
SUM(CASE WHEN s.STOCKWEEK = 8 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk8,
SUM(CASE WHEN s.STOCKWEEK = 9 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk9,
SUM(CASE WHEN s.STOCKWEEK = 10 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk10,
SUM(CASE WHEN s.STOCKWEEK = 11 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk11,
SUM(CASE WHEN s.STOCKWEEK = 12 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk12,
SUM(CASE WHEN s.STOCKWEEK = 13 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk13,
SUM(CASE WHEN s.STOCKWEEK = 14 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk14,
SUM(CASE WHEN s.STOCKWEEK = 15 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk15,
SUM(CASE WHEN s.STOCKWEEK = 16 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk16,
SUM(CASE WHEN s.STOCKWEEK = 17 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk17,
SUM(CASE WHEN s.STOCKWEEK = 18 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk18,
SUM(CASE WHEN s.STOCKWEEK = 19 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk19,
SUM(CASE WHEN s.STOCKWEEK = 20 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk20,
SUM(CASE WHEN s.STOCKWEEK = 21 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk21,
SUM(CASE WHEN s.STOCKWEEK = 22 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk22,
SUM(CASE WHEN s.STOCKWEEK = 23 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk23,
SUM(CASE WHEN s.STOCKWEEK = 24 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk24,
SUM(CASE WHEN s.STOCKWEEK = 25 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk25,
SUM(CASE WHEN s.STOCKWEEK = 26 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk26,
SUM(CASE WHEN s.STOCKWEEK = 27 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk27,
SUM(CASE WHEN s.STOCKWEEK = 28 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk28,
SUM(CASE WHEN s.STOCKWEEK = 29 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk29,
SUM(CASE WHEN s.STOCKWEEK = 30 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk30,
SUM(CASE WHEN s.STOCKWEEK = 31 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk31,
SUM(CASE WHEN s.STOCKWEEK = 32 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk32,
SUM(CASE WHEN s.STOCKWEEK = 33 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk33,
SUM(CASE WHEN s.STOCKWEEK = 34 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk34,
SUM(CASE WHEN s.STOCKWEEK = 35 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk35,
SUM(CASE WHEN s.STOCKWEEK = 36 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk36,
SUM(CASE WHEN s.STOCKWEEK = 37 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk37,
SUM(CASE WHEN s.STOCKWEEK = 38 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk38,
SUM(CASE WHEN s.STOCKWEEK = 39 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk39,
SUM(CASE WHEN s.STOCKWEEK = 40 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk40,
SUM(CASE WHEN s.STOCKWEEK = 41 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk41,
SUM(CASE WHEN s.STOCKWEEK = 42 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk42,
SUM(CASE WHEN s.STOCKWEEK = 43 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk43,
SUM(CASE WHEN s.STOCKWEEK = 44 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk44,
SUM(CASE WHEN s.STOCKWEEK = 45 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk45,
SUM(CASE WHEN s.STOCKWEEK = 46 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk46,
SUM(CASE WHEN s.STOCKWEEK = 47 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk47,
SUM(CASE WHEN s.STOCKWEEK = 48 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk48,
SUM(CASE WHEN s.STOCKWEEK = 49 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk49,
SUM(CASE WHEN s.STOCKWEEK = 50 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk50,
SUM(CASE WHEN s.STOCKWEEK = 51 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk51,
SUM(CASE WHEN s.STOCKWEEK = 52 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk52,
SUM(CASE WHEN s.STOCKWEEK = 53 THEN s.QTY_INSTOCK + s.QTY ELSE 0 END) Wk53
FROM
(
SELECT s.STOCK_CODE, s.DESCRIPTION, DATEPART(YEAR, s.FORECASTDATE) STOCKYEAR, DATEPART(WEEK, s.FORECASTDATE) STOCKWEEK, SUM(s.QTY_INSTOCK) QTY_INSTOCK, SUM(s.QUANTITY) QTY
FROM #Stock s
GROUP BY s.STOCK_CODE, s.DESCRIPTION, DATEPART(YEAR, s.FORECASTDATE), DATEPART(WEEK, s.FORECASTDATE)
) s
GROUP BY s.STOCK_CODE, s.DESCRIPTION, s.STOCKYEAR
ORDER BY s.STOCK_CODE, s.DESCRIPTION, s.STOCKYEAR
Group by the code, desc, year and week and then sum by week for each week of the year (adding extra week depending on day beginning / end of the year falls.

Resources