Case When bringing back two lines rather than one - sql

Hi all I have some code I'm working on, and what I need to do I'm sure is relatively easy, however I'm struggling on a Case statement
What I need to do;
Bring back the data set to make into a table within SSRS, split by Year, then Usage Month, then by Billing Tier
Issue;
Billing Tiers are 0,1,4,5
0 is historic data and I need to show this as 1, then add 0 and original tier 1 together
What I've done so far;
DECLARE #UsageMonth DATE = '20170401'
DECLARE #YEAR INT = '2017'
DECLARE #BillingTier2 INT = 1;
SELECT YEAR(UsageMonth) AS [Year],
UsageMonth,
--Billingtier,
CASE WHEN billingtier = 0 THEN 1 ELSE billingtier END AS BillingTier2,
SuppliesBilled = COUNT(DISTINCT c.CoreMPAN),
CreditKwH = SUM(CASE WHEN c.IsCredit = 1 THEN c.ConsumptionUnits ELSE 0 END),
DebitKwH = SUM(CASE WHEN c.IsCredit = 0 THEN c.ConsumptionUnits ELSE 0 END),
TotalKwh = SUM(c.ConsumptionUnits),
CreditAmount = SUM(CASE WHEN c.IsCredit = 1 THEN c.ConsumptionAmount ELSE 0 END),
DebitAmount = SUM(CASE WHEN c.IsCredit = 0 THEN c.ConsumptionAmount ELSE 0 END),
TotalAmount= SUM(c.ConsumptionAmount),
UnitRate = SUM(c.ConsumptionAmount) / NULLIF(SUM(c.ConsumptionUnits), 0),
StandingCharge = SUM(c.StandingChargeAmount),
CCL = SUM(c.CCLAmount)
FROM dbo.table1 c
WHERE YEAR(UsageMonth) = #YEAR
AND UsageMonth = #UsageMonth
GROUP BY YEAR(UsageMonth), UsageMonth, Billingtier, CASE WHEN billingtier = 0 THEN 1 ELSE billingtier END
The issue I have here is that this brings back both all columns that were previously 0 as 1 on one line, as well as another line where billing tier is actually 1, thus giving me two lines for '1', where it should be one line with both billing tier 1 and 0 added together
Data Expected
Year UsageMonth BillingTier2 SuppliesBilled CreditKwH DebitKwH TotalKwh CreditAmount DebitAmount TotalAmount UnitRate StandingCharge CCL
2017 01/04/2017 1 3296 -4348786.008 7219573.706 2870787.699 -523979.1005 866478.4812 342499.3807 0.238118 22394.5114 10685.7546
2017 01/04/2017 4 27 -59415.7663 65843.4963 6427.73 -9269.5841 10359.9353 1090.3512 0.169632 118.5181 21.3836
2017 01/04/2017 5 515 -524035.4192 943647.2675 419611.8483 -105349.1449 189478.524 84129.3791 0.200493 6581.5 1567.7762
Data receiving
Year UsageMonth BillingTier2 SuppliesBilled CreditKwH DebitKwH TotalKwh CreditAmount DebitAmount TotalAmount UnitRate StandingCharge CCL
2017 01/04/2017 1 3124 -4348786.008 7219573.706 2870787.699 -523979.1005 866478.4812 342499.3807 0.119305 22394.5114 10685.7546
2017 01/04/2017 4 27 -59415.7663 65843.4963 6427.73 -9269.5841 10359.9353 1090.3512 0.169632 118.5181 21.3836
2017 01/04/2017 5 515 -524035.4192 943647.2675 419611.8483 -105349.1449 189478.524 84129.3791 0.200493 6581.5 1567.7762
As you can see, all the sums and data match, bar the Supplies billed as 0 originally (172) missing from the Case statement when counted
Any help here would be greatly appreciated
Cheers

As you are using DISTINCT inside the COUNT function as below-
SuppliesBilled = COUNT(DISTINCT c.CoreMPAN)
Its decreasing the number of COUNT if there are multiple c.CoreMPAN avilable with same value. Hoe you are aware of it. If this is not expected, you can try with removing the DISTINCT command from COUNT as below-
SuppliesBilled = COUNT(c.CoreMPAN)

Related

Using calculated column within SQL query

I need help with a subquery. I think I’m close but not quite sure. I want to use a calculated column within another calculation. In the example want to use “numerator” in the calculation of the “denominator”. I’m new to subqueries.
SELECT
sum(case when denominator=1 and q10=1 then 1 else 0 end) as numerator
FROM (
SELECT sum(case when q5=1 and q6=1 then 1 else 0 end) as denominator
FROM datasource
q5
q6
q10
1
1
0
0
1
0
0
0
1
I want to calculate a “denominator” column where it’s 1 if q5 and q6 are equal to 1 or else “denominator”=0. Then calculate a “numerator” column if the calculated denominator column is 1 and q10 is 1 then “numerator”=1 or else “numerator”=0. You can ignore the sum command cause I just wanted to sum the columns at the end but for the purpose of the question it isn’t important
Update…
I tried the below query as suggested and get the error “Expression not in GROUP BY key”
SELECT sum(case when denominator=1 and q10 = 1 then 1 else 0 end) as numerator
FROM (
SELECT q10,
sum(case when q5=1 and q6=1 then 1 else 0 end) as denominator
FROM datasource) t
I haven't added the aggregation part, but I think this will get you close to what you are trying to do.
SELECT case when denominator=1 and q10 = 1 then 1 else 0 end as numerator
FROM (
SELECT q10,
case when q5=1 and q6=1 then 1 else 0 end as denominator
FROM datasource
GROUP BY q10) t

Condition SUM in SQL

I want to calculate con_Amount field & want to put total to D01,D02,....D31 on the condition of Con_PubDate.
if Con_PubDate field Day = 1 then I want to put the total to D01,if Con_PubDate field Day = 2 then I want to put the total to D02,likewise upto Day = 31 then I want to put the total to D31
I try following code in stored procedure but it had an error. Some one please help me to solve this problem.
SELECT Con_Cnt_Code,
Con_Dst_Code,
Con_Cor_Code,
SUM(CASE
WHEN DATEPART(DAY,Con_PubDate) = 1 THEN con_Amount
ELSE
SUM(CASE
WHEN DATEPART(DAY,Con_PubDate) = 2 THEN con_Amount
ELSE
SUM(CASE
WHEN DATEPART(DAY,Con_PubDate) = 31 THEN con_Amount
END) AS D31
END) AS D02
END) AS D01
FROM Contributions
GROUP BY Con_Cnt_Code,Con_Dst_Code,Con_Cor_Code
You probably want each conditional sum of a CASE expression as a separate item in your select list, something like this:
SELECT
Con_Cnt_Code,
Con_Dst_Code,
Con_Cor_Code,
SUM(CASE WHEN DATEPART(DAY,Con_PubDate) = 1 THEN con_Amount END) AS D01,
SUM(CASE WHEN DATEPART(DAY,Con_PubDate) = 2 THEN con_Amount END) AS D02,
-- and possibly other days as well
SUM(CASE WHEN DATEPART(DAY,Con_PubDate) = 31 THEN con_Amount END) AS D31
FROM Contributions
GROUP BY
Con_Cnt_Code, Con_Dst_Code, Con_Cor_Code;
By default, SUM will ignore NULL values, so you might not need an ELSE condition in your CASE expressions. If you add one, you may default the amount to sum to zero.

Transact SQL - Table with different Record types requiring calculation

I have a table of invoices and Record_Types that I need to reconcile to open invoice report. I have the process down and know what I need to do. Just dont know how to properly structure the query and would prefer to not create 3 tables.
Record Types.
Invoice = 1 Credit = 5 Payment = 7
Invoice_Number, Record_Type, Dollar figure
Outstanding_Balance = Invoice(1) -(Payment(7)-(Credit))
Invoice_number Record_type Gen_Numeric_3
Basically I need to take the record_Type 1 and subtract the total of record type 7's from the below.
Invoice_Num Rec_Type Dollar_Amt
00820437 1 536.7700000000
00820437 7 469.6200000000
00820437 7 67.1500000000
Any advice would be great. messer
You can do this with aggregation and case statements:
SELECT invoice_num,
SUM(CASE WHEN rec_type = 1 THEN dollar_amt ELSE 0 END) - (SUM(CASE WHEN rec_type=7 THEN dollar_amt ELSE 0 END) - SUM(CASE WHEN rec_type=5 THEN dollar_amt ELSE 0 END)) as outstanding_balance
FROM yourtable
GROUP BY invoice_num

SELECTING with multiple WHERE conditions on same table

I am currently working on my sql query that looks like this
SELECT reference.agent_ID, reference.policy_ID, Count(reference.status_ID) AS [Quoted Motor Breakdown] , Sum(IIf([status_ID]=1,1,0)) AS sold
FROM reference
GROUP BY reference.agent_ID, reference.policy_ID
HAVING (((reference.policy_ID)=1));
So results show as below
Agent| Number of policies quoted for Motor breakdown|number of policies Motor breakdown sold
I would like to add more columns to the same table showing results for remaining type of policies :
reference.policy_ID=2 (Travel),
reference.policy_ID=3 (Home Insurance) next to one agent
example:
Mr Smith|Quoted Motor Breakdown| Sold| Quoted Motor Travel| Sold
I would also like to my query to show result=0 if there wos no quote for specific type of policy
Any advise would be much appreciated
Thank you
I think you want conditional aggregation:
SELECT r.agent_ID,
SUM(CASE WHEN r.policy_ID = 1 THEN 1 ELSE 0 END) AS [Quoted Motor Breakdown],
SUM(CASE WHEN r.policy_ID = 1 AND status_ID = 1 THEN 1 ELSE 0 END) AS sold,
SUM(CASE WHEN r.policy_ID = 2 THEN 1 ELSE 0 END) AS NumTravel,
SUM(CASE WHEN r.policy_ID = 3 THEN 1 ELSE 0 END) AS NumHomeInsurance
FROM reference r
GROUP BY r.agent_ID;
If you are using MS Access, then you'll need to use the non-standard iif() instead:
SELECT r.agent_ID,
SUM(iif(r.policy_ID = 1, 1, 0)) AS [Quoted Motor Breakdown],
SUM(iif(r.policy_ID = 1 AND status_ID = 1, 1, 0)) AS sold,
SUM(iif(r.policy_ID = 2, 1, 0)) AS NumTravel,
SUM(iif(r.policy_ID = 3, 1, 0)) AS NumHomeInsurance
FROM reference as r
GROUP BY r.agent_ID;

SQL Beginner : Multiple where clause from same table

I'm very new to SQL and am not sure how to accomplish the following.
I have a list of meter IDs that have a years worth of Target and a years worth of Budget data assigned, however these are all held in the same table with an identifier (TargetType) to distinguish between Target(0) & Budget(1)
ID TARGETTYPE VALUE01 VALUE02 ...(etc up to VALUE12)
123 0 1001 1100
123 1 9000 9100
456 0 5000 5100
456 1 8000 8100
Desired result would be also include information from a couple of other tables want to add that in as well
My query so far can bring through one set of data :
PARAMETERS
[Utility] Text;
SELECT
Contacts.Group,
Contacts.Site,
Points.ID,
Points.Utility,
Points.MPAN1,
Target.Value_01 AS [Target JAN],
Target.Value_02 AS [Target FEB],
Target.Value_03 AS [Target MAR],
Target.Value_04 AS [Target APR],
Target.Value_05 AS [Target MAY],
Target.Value_06 AS [Target JUN],
Target.Value_07 AS [Target JUL],
Target.Value_08 AS [Target AUG],
Target.Value_09 AS [Target SEP],
Target.Value_10 AS [Target OCT],
Target.Value_11 AS [Target NOV],
Target.Value_12 AS [Target DEC]
FROM
((Contacts INNER JOIN Points ON Contacts.[Id] = Points.[Contacts_Id])
INNER JOIN Contracts ON Points.[Id] = Contracts.[Point_Id])
INNER JOIN Target ON Points.Id = Target.DataSetId
WHERE
Points.UtilityType =[Utility]
ORDER BY
Contacts.ClientGroup;
Desired Output
(the values would go TargetJan through to TargetDec and then BudgetJan through to BudgetDec but I've not shown for brevity):
Group Site ID Utility MPAN1 TargetJan TargetFeb etc... BudgetJan BudgetFeb etc...
ABC London 123 Gas 123456 1,000 1,100 9,000 9,100
ABC NewYork 456 Gas ABC123 5,000 5,100 8,000 8,100
How can I add in the same fields but depending on the value of Target.TargetType, I'm guessing that it is a Union query, but I have no idea.
Any pointers of where to start would be gratefully received :)
UPDATE #1
Thank you for your help. I think I understand the query, however there is still a bit of odd behaviour I can't figure out.
QUERY USED
SELECT
Points.ID,
SUM(CASE WHEN Target.TargetType = '0' THEN Target.Value_01 else 0 end) AS [TGT JAN],
SUM(CASE WHEN Target.TargetType = '0' THEN Target.Value_02 else 0 end) AS [TGT FEB],
FROM
((Contacts INNER JOIN Points ON Contacts.[Id] = Points.[Contacts_Id])
INNER JOIN Contracts ON Points.[Id] = Contracts.[Point_Id] )
INNER JOIN Target ON Points.Id = Target.DataSetId
GROUP BY
Points.ID
ORDER BY
Points.ID;
Where my data row only has one Target.Type then the query returns as desired:
RAW DATA
ID TARGETTYPE VALUE_01 VALUE_02
10079 0 7642 5735
RESULT
ID TGTJAN TGTFEB
10079 7642 5735
However ... If I have an ID with 2 or more TargetTypes then the Value output is being multiplied by 6.
RAW DATA
ID TARGETTYPE VALUE_01 VALUE_02
7423 0 58339 57441
7423 1 1663 1637
RESULT
ID TGTJAN TGTFEB
7423 350034 344646
I have experimented and removed the INNER JOIN to the contacts table (although I will need that join) and then it all works as expected ???? So why is the Contacts JOIN causing this issue ?
Please put me out of my misery as I can not work out what is going on !
What about using a select case syntax?
select
...
sum(case when Target.TargetType = 'Target' then Target.Value_01 else 0 end) AS [Target JAN],
sum(case when Target.TargetType = 'Budget' then Target.Value_01 else 0 end) AS [Budget JAN],
...
group by
--all fields in the select list which are not aggregates
For future reference I have solved this problem by rewriting the joins and changing the way the data is held so I don't need to reference the Contracts table, which is redudant and probably contributed to my bizarre x by 6 problem.
SELECT
Points.ID,
SUM(CASE WHEN Target.TargetType = '0' THEN Target.Value_01 else 0 end) AS [TGT kWh JAN],
SUM(CASE WHEN Target.TargetType = '0' THEN Target.Value_02 else 0 end) AS [TGT kWh FEB],
SUM(CASE WHEN Target.TargetType = '1' THEN Target.Value_01 else 0 end) AS [BUD kWh JAN],
SUM(CASE WHEN Target.TargetType = '1' THEN Target.Value_02 else 0 end) AS [BUD kWh FEB]
FROM (Contacts INNER JOIN Points ON Contacts.Id = Points.Contacts_Id)
INNER JOIN Target ON Points.Id = Target.DataSetId
GROUP BY
Points.ID
ORDER BY
Points.ID;