SQL Server Converting Rows to Columns - sql

I am currently extracting data using 3 different tables, and below is the output.
Current Result:
Query Used:
SELECT
dbo.TableB.TrackingID, dbo.TableA.FinancialID,
dbo.TableA.ParcelCode, dbo.TableA.TotalAmount,
dbo.TableB.FinanceType, dbo.TableB.TransactionType,
dbo.TableC.CustID
FROM
dbo.TableA
INNER JOIN
dbo.TableB ON dbo.TableA.FinancialID = dbo.TableB.FinancialID
INNER JOIN
dbo.TableC ON dbo.TableB.TrackingID = dbo.TableC.TrackingID
WHERE
(dbo.TableB.TrackingID = '17006218AU')
I would like to have the following output:
Desired Output:

You can get the output you desire with grouping and some CASE statements inside SUM aggregate functions:
SELECT
dbo.TableB.TrackingID,
dbo.TableA.ParcelCode,
dbo.TableC.CustID,
SUM(CASE WHEN dbo.TableB.FinanceType = 'Invoice' THEN dbo.TableA.TotalAmount ELSE 0 END) AS TotalAmount,
SUM(CASE WHEN dbo.TableB.FinanceType = 'Invoice' AND TransType='Card' THEN dbo.TableA.TotalAmount ELSE 0 END) AS CardInvoice,
SUM(CASE WHEN dbo.TableB.FinanceType = 'Invoice' AND TransType='Cash' THEN dbo.TableA.TotalAmount ELSE 0 END) AS CashInvoice,
SUM(CASE WHEN dbo.TableB.FinanceType = 'PaymentRecepit' THEN dbo.TableA.TotalAmount ELSE 0 END) AS CardPaymentRecepit
FROM dbo.TableA
INNER JOIN dbo.TableB ON dbo.TableA.FinancialID = dbo.TableB.FinancialID
INNER JOIN dbo.TableC ON dbo.TableB.TrackingID = dbo.TableC.TrackingID
WHERE
dbo.TableB.TrackingID = '17006218AU'
GROUP BY
dbo.TableB.TrackingID,
dbo.TableA.ParcelCode,
dbo.TableC.CustID

Related

Using an array in conditional summation with grouping

I have the sql query thats work fine
SELECT
CAST(L.CreationUtcDateTime AS DATE),
SUM(L.Profit),
SUM(CASE WHEN (L.Network = 0 OR L.Network = 1) THEN L.Profit ELSE 0 END),
SUM(CASE WHEN (L.Network != 0 AND L.Network != 1) THEN L.Profit ELSE 0 END)
FROM
[dbo].[Leads] L WITH (NOLOCK)
LEFT JOIN [dbo].[Transactions] S WITH (NOLOCK) ON L.TransactionId = S.Id
GROUP BY
CAST(L.CreationUtcDateTime AS DATE);
I need to make it more generic by using variables instead of hard-coded constants.
I changed the query to:
DECLARE #matchNetworks TABLE (id int)
INSERT #matchNetworks(id) VALUES (0),(1)
SELECT
CAST(L.CreationUtcDateTime AS DATE),
SUM(L.Profit),
SUM(CASE WHEN (L.Network in (SELECT ID from #matchNetworks)) THEN L.Profit ELSE 0 END),
SUM(CASE WHEN (L.Network not in (SELECT ID from #matchNetworks)) THEN L.Profit ELSE 0 END)
FROM
[dbo].[Leads] L WITH (NOLOCK)
LEFT JOIN [dbo].[Transactions] S WITH (NOLOCK) ON L.TransactionId = S.Id
GROUP BY
CAST(L.CreationUtcDateTime AS DATE);
And now i have an error:
Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
How can I use the predefined array of network ids in my query to avoid an error?
Move the comparison to the FROM clause using a LEFT JOIN:
SELECT CAST(L.CreationUtcDateTime AS DATE),
SUM(L.Profit),
SUM(CASE WHEN mn.ID IS NOT NULL THEN L.Profit ELSE 0 END),
SUM(CASE WHEN mn.ID IS NULL THEN L.Profit ELSE 0 END)
FROM [dbo].[Leads] L LEFT JOIN
[dbo].[Transactions] S
ON L.TransactionId = S.Id LEFT JOIN
#matchNetworks mn
ON mn.ID = l.Network
GROUP BY CAST(L.CreationUtcDateTime AS DATE);

How to join two sub queries and find the difference of attribute values in SQL

From the below query, I want to know how to combine these two sub-queries and also find the difference of values of the attributes specified for two different years.
I had tried joining them using joins, but I do not have a common attribute on which I can combine them as they are for two different years. I need to find the difference in order to compute the change as seen in the attached picture. Can anyone help?
(select (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD,1,4)))-1 as 'Year1',
SUM(CASE WHEN dh.HOME = 'f' THEN 1 else 0 END) as 'foriegn1',
SUM(CASE WHEN dh.HOME = 'o' THEN 1 else 0 END) AS 'outofstate1',
SUM(CASE WHEN dh.HOME = 'i' THEN 1 else 0 END) AS 'texas1',
SUM(CASE WHEN dh.HOME = 'u' THEN 1 else 0 END) AS 'Unknown1',
COUNT(*) as Totalenrollment
FROM dw_enrollment_F d
inner join dim_Time t
on d.TIME_KEY = t.TIME_KEY
inner join dim_Home dh
on d.HOME_KEY = dh.HOME_KEY
inner join dim_Student_Level sl
on d.STUDENT_LEVEL_KEY = sl.STUDENT_LEVEL_KEY
where t.ACADEMIC_PERIOD_all =20162
and t.ACADEMIC_PERIOD_ALL not in('20157','20165','20168','20169','20167')
GROUP BY (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD,1,4)) ) -1)
(select (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD,1,4)))-1 as 'Year2',
SUM(CASE WHEN dh.HOME = 'f' THEN 1 else 0 END) as 'foriegn2',
SUM(CASE WHEN dh.HOME = 'o' THEN 1 else 0 END) AS 'outofstate2',
SUM(CASE WHEN dh.HOME = 'i' THEN 1 else 0 END) AS 'texas2',
SUM(CASE WHEN dh.HOME = 'u' THEN 1 else 0 END) AS 'Unknown2',
COUNT(*) as Totalenrollment2
FROM dw_enrollment_F d
inner join dim_Time t
on d.TIME_KEY = t.TIME_KEY
inner join dim_Home dh
on d.HOME_KEY = dh.HOME_KEY
inner join dim_Student_Level sl
on d.STUDENT_LEVEL_KEY = sl.STUDENT_LEVEL_KEY
where t.ACADEMIC_PERIOD_all = 20172
and t.ACADEMIC_PERIOD_ALL not in('20157','20165','20168','20169','20167')
GROUP BY (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD,1,4)) ) -1)

Sum values are inflated when I join another table

I have two queries that return the result sets I want, it is one row per user per day. The problem is that when I try to join the two queries, by userid, I get inflated results because the user is in the table multiple times for each day. How do I join them and avoid having the inflated results?
**Query 1**
SELECT AAL.UserID
, SUM(AAL.Dur)/60 AS 'LIM'
, SUM(CASE When AAL.DUR = 'av' then AAL.Dur/60
Else 0 END) AS 'AVAIL'
FROM WG
INNER JOIN AAL
on WG.UserID=AAL.UserID
and WG.SiteID=AAL.SiteID
WHERE WG.WG = 'OP'
AND DATEDIFF(day,AAL.Date,GETDATE()) = 1
GROUP BY AAL.UserID
**Query 2**
SELECT R.UserID
, SUM(CASE When R.StID = 4 then 1
Else 0 End) AS 'Rf Ct'
FROM R
INNER JOIN WG
on R.UserID = WG.UserID
WHERE WG.WG = 'OP'
AND DATEDIFF(day,R.Date,GETDATE()) = 1
GROUP BY R.UserID
**JOIN ATTEMPT**
SELECT AAL.UserID
, SUM(AAL.Dur)/60 AS 'LIM'
, SUM(CASE When AAL.DUR = 'av' then AAL.Dur/60
Else 0 END) AS 'AVAIL'
, SUM(CASE When R.StID = 4 then 1
Else 0 End) AS 'Rf Ct'
FROM WG
INNER JOIN AAL
on WG.UserID=AAL.UserID
and WG.SiteID=AAL.SiteID
INNER JOIN R
on AAL.UserID=R.UserID
WHERE WG.WG = 'OP'
AND DATEDIFF(day,AAL.Date,GETDATE()) = 1
GROUP BY AAL.UserID
You are not using WB in the query. So, just use exists or in:
SELECT R.UserID, SUM(CASE When R.StID = 4 then 1 Else 0 End) AS 'Rf Ct'
FROM R
WHERE DATEDIFF(day, R.Date, GETDATE()) = 1 AND
EXISTS (SELECT 1 FROM WB WHERE R.UserID = WG.UserID AND WG.WG = 'OP')
GROUP BY R.UserID;
You should understand the reason why the number gets multiplied -- multiple rows in WG correspond to a single R.ID.

Complex Case Statement Issue - Oracle SQL

Wrote the query below, but am getting multiplied amounts because the aggregation needs to occur before the case statements. Would love some advice on the best way to structure this.
Select Store, CUSTID, CUST.ID_CUST,
Sum(
CASE
WHEN Cust_Gift.Code_Status = 'C' AND Gift_Item.FLAG_STORE_LOC = 'N'
THEN Cust_Gift.AMT_PAID ELSE 0
END) GiftAmt,
Sum(
CASE WHEN Cust_Gift.Code_Status = 'C' AND Gift_Item.FLAG_STORE_LOC = 'Y'
THEN Cust_Gift.AMT ELSE 0
END) CustGiftAmt,
Sum(
CASE WHEN Cust_Coupon.Code_Status = 'C'
THEN Cust_Coupon.AMT
ELSE 0
END) CouponAmt,
Sum(CASE WHEN Cust_Sports.Status = 'C'
THEN Cust_Sports.AMT
ELSE 0
END) SportsAmt
FROM CUST
LEFT OUTER JOIN CUST_GIFT
ON CUST.ID_CUST = CUST_GIFT.ID_CUST
LEFT OUTER JOIN CUST_COUPON
ON CUST.ID_CUST = CUST_COUPON.ID_CUST
LEFT OUTER JOIN CUST_SPORTS
ON CUST.ID_CUST = CUST_SPORTS.ID_CUST
INNER JOIN GIFT_ITEM
ON CUST_GIFT.ID_GIFT_ITEM = GIFT_ITEM.ID_GIFT_ITEM
WHERE (STORE = 'M669098' OR STORE = 'M66923434' )
Group by CustID, Store, CUST.ID_CUST
This is one way you could do it:
SELECT cust.store,
cust.custid,
cust.id_cust,
gift.giftamt,
gift.custgift,
cpn.couponamt,
sprt.sportsamt
FROM cust
LEFT OUTER JOIN (SELECT id_cust,
SUM(CASE WHEN cg.code_status = 'C' AND gi.flag_store_loc = 'N' THEN cg.amt_paid END) giftamt,
SUM(CASE WHEN cg.code_status = 'C' AND gi.flag_store_loc = 'Y' THEN cg.amt_paid END) custgiftamt
FROM cust_gift cg
INNER JOIN gift_item gi ON cg.id_gift_item = gi.id_gift_item) gift ON cust.id_cust = gift.id_cust
LEFT OUTER JOIN (SELECT id_cust,
SUM(CASE WHEN code_status = 'C' THEN amt END) couponamt
FROM cust_coupon) cpn ON cust.id_cust = cpn.id_cust
LEFT OUTER JOIN (SELECT id_cust,
SUM(CASE WHEN status = 'C' THEN amt END) sportsamt
FROM cust_sports) sprt ON cust.id_cust = sprt.id_cust
WHERE (STORE = 'M669098' OR STORE = 'M66923434');

SQL QUERY with subquery Optimization

how can i optimize these query
SELECT
mp.ProviderName
,(SELECT count(mc.ClaimSubmissionID) FROM dbo.MST_Claim mc WHERE mc.HeaderID=mpach.HeaderID AND mc.IsActive=1) AS total_claim
,(SELECT count(mc.ClaimSubmissionID) FROM dbo.MST_Claim mc WHERE mc.HeaderID=mpach.HeaderID AND mc.op=1) AS total_op
,(SELECT count(mc.ClaimSubmissionID) FROM dbo.MST_Claim mc WHERE mc.HeaderID=mpach.HeaderID AND mc.ip=1) AS total_ip
FROM dbo.MST_PriorAuthorization_Claim_Header mpach
INNER JOIN dbo.MS_Provider mp ON mp.Provider_ID = mpach.Provider_ID
Use Sum of CASE Statements to avoid all those subqueries.
SELECT
mp.ProviderName,
SUM(CASE WHEN mc.IsActive=1 THEN 1 ELSE 0 END ) AS total_claim,
SUM(CASE WHEN mc.op=1 THEN 1 ELSE 0 END ) AS total_op,
SUM(CASE WHEN mc.ip=1 THEN 1 ELSE 0 END ) AS total_ip
FROM dbo.MST_PriorAuthorization_Claim_Header mpach
INNER JOIN dbo.MS_Provider mp ON mp.Provider_ID = mpach.Provider_ID
INNER JOIN dbo.MST_Claim mc ON mc.HeaderID=mpach.HeaderID
You can modify your query using a CASE statement like below
SELECT
mp.ProviderName
,sum(case when mc.IsActive=1 then mc.ClaimSubmissionID else 0 end) AS total_claim,
sum(case when mc.op=1 then mc.ClaimSubmissionID else 0 end) AS total_op
sum(case when mc.ip=1 then mc.ClaimSubmissionID else 0 end) AS total_ip
FROM dbo.MST_PriorAuthorization_Claim_Header mpach
INNER JOIN dbo.MS_Provider mp ON mp.Provider_ID = mpach.Provider_ID
JOIN dbo.MST_Claim mc ON mc.HeaderID = mpach.HeaderID;