Sum of SQL instead of a list result - sql

Instead of have a list of rows with daily budget, I just wan't the total SUM of DalyBudget.
How do I do that?
SELECT
(b.MonthBudget /
SUM(wd.WorkingDay) OVER (PARTITION BY YEAR(wd.date), MONTH(wd.date))
)
as DalyBudget
FROM [Navision4].[dbo].[Salesboard Working Days] wd OUTER APPLY
(SELECT COALESCE(ABS(SUM(Amount)), 0) as MonthBudget
FROM [Navision4].[dbo].[Selek Danmark$G_L Budget Entry] b
WHERE MONTH(wd.Date) = MONTH(b.Date) AND
YEAR(wd.date) = YEAR(b.Date) AND
b.[Budget Name] = '2020C' AND
b.[G_L Account No_] LIKE '3%'
) b
WHERE wd.WorkingDay = 1 AND
wd.SalesPersonCode IS NULL AND
wd.companycode = 'Selek Danmark' AND
wd.[Date] >= '2020-07-27' AND wd.[Date] <= '2020-08-17'
Current result:
I'm not so good til advanced SQL, and this dosen't work
SUM(
(b.MonthBudget /
SUM(wd.WorkingDay) OVER (PARTITION BY YEAR(wd.date), MONTH(wd.date))
)
)
as DalyBudget

This is because of your OUTER APPLY results, simply add DISTINCT keyword before you select it.
SELECT DISTINCT
(b.MonthBudget / SUM(wd.WorkingDay) OVER (PARTITION BY YEAR(wd.date), MONTH(wd.date))) AS DalyBudget
FROM [Navision4].[dbo].[Salesboard Working Days] wd OUTER APPLY
(
SELECT COALESCE(ABS(SUM(Amount)), 0) as MonthBudget
FROM [Navision4].[dbo].[Selek Danmark$G_L Budget Entry] b
WHERE MONTH(wd.Date) = MONTH(b.Date) AND YEAR(wd.date) = YEAR(b.Date) AND
b.[Budget Name] = '2020C' AND b.[G_L Account No_] LIKE '3%'
)b
WHERE wd.WorkingDay = 1 AND wd.SalesPersonCode IS NULL AND wd.companycode = 'Selek Danmark' AND
wd.[Date] >= '2020-07-27' AND wd.[Date] <= '2020-08-17'

Related

How to get biggest value from 2 or more fields in a subquery

I have a table with customers that I join with a fact table with sales, based on invoices.
What I need from my report is to get in first part the biggest value of sales based on the incoming order type (1,2,3,C,D) for a customer for last year. And in the second part to get the same but for current year. What I get as result from my current query is all incoming order types with the customer revenue made for each of them. I tried with outer apply as subquery to get only the top 1 value ordered by revenue descending, but in the result I get the same - For all order types the customer revenue. Please help! I hope my explanation isn't understood only by me (happens a lot..)
use dwh01;
WITH OrderTypeUsedLY AS
(
SELECT
c.CustomerKey
,c.BranchId
,c.CustomerId
,c.CustomerName
,ISNULL(SUM(y.[Sale_Revenue]), 0) as [Sale_Revenue_LY]
,ISNULL(SUM(y.[Sale_GrossMarginTotal]), 0) as [Sale_GrossMarginTotal_LY]
,y.IncomingOrderTypeId as IncomingOrderType_LY
FROM live.DimCustomer c
left join (SELECT s.CustomerKey,iot.IncomingOrderTypeid, s.[Sale_Revenue], s.[Sale_GrossMarginTotal] FROM [dwh01].[live].[FactSales] s
inner join live.DimDate d
on d.DateId = s.PostingDateKey
inner join live.DimIncomingOrderType iot on iot.IncomingOrderTypeKey = s.IncomingOrderTypeKey
where s.ReportCurrencyId = 'LC'
and D.Year = YEAR(GETDATE())-1 --- Last Year
) y on c.CustomerKey = y.CustomerKey
where c.CustomerKey = '157053'
group by c.CustomerKey, c.CustomerId, c.CustomerName, c.BranchId, y.IncomingOrderTypeId
),
--*********************************************************************************************************************************--
OrderTypeCY as(
SELECT
c.CustomerKey
,c.BranchId
,c.SalesRepKey
,c.CustomerId
,c.CustomerName
,ISNULL(SUM(y.[Sale_Revenue]), 0) as [Sale_Revenue_CY]
,ISNULL(SUM(y.[Sale_GrossMarginTotal]), 0) as [Sale_GrossMarginTotal_CY]
,y.IncomingOrderTypeId as IncomingOrderType_CY
FROM live.DimCustomer c
left join (SELECT s.CustomerKey,iot.IncomingOrderTypeid, s.[Sale_Revenue], s.[Sale_GrossMarginTotal] FROM [dwh01].[live].[FactSales] s
inner join live.DimDate d
on d.DateId = s.PostingDateKey
inner join live.DimIncomingOrderType iot on iot.IncomingOrderTypeKey = s.IncomingOrderTypeKey
where s.ReportCurrencyId = 'LC'
and D.Year = YEAR(GETDATE()) --- Current Year
) y on c.CustomerKey = y.CustomerKey
where c.CustomerKey = '157053'
group by c.CustomerKey, c.CustomerId, c.CustomerName, c.BranchId, y.IncomingOrderTypeId, c.SalesRepKey
)
--*********************************************************************************************************************************--
SELECT
otly.BranchId,
rep.SalesRepId,
rep.SalesRepName,
otly.CustomerId,
otly.CustomerName,
otly.Sale_Revenue_LY,
otly.Sale_GrossMarginTotal_LY,
IncomingOrderType_LY,
otcy.Sale_Revenue_CY,
otcy.Sale_GrossMarginTotal_CY,
IncomingOrderType_CY
from OrderTypeUsedLY otly
left join OrderTypeCY otcy
on otly.CustomerKey = otcy.CustomerKey
join live.DimCustomer cus on cus.CustomerKey = otcy.CustomerKey
join live.DimSalesRep rep on rep.SalesRepKey = otcy.SalesRepKey
order by otcy.Sale_Revenue_CY desc, otly.Sale_Revenue_LY desc
,rep.SalesRepId
And here is the outer apply I tried:
outer apply (
SELECT top 1
iot.IncomingOrderTypeId,
Sale_Revenue
FROM [dwh01].[live].DimIncomingOrderType iot
where iot.IncomingOrderTypeKey = y.IncomingOrderTypeKey
order by Sale_Revenue desc) x
In the first select ( with OrderTypeUsed_LY ) I get this:
And I get the same in the second select, but with the values for current year.
The purpose of the report is to see the difference in the incoming order type most used (most profit made with it) for a customer last year and to see if he continues to use it this year, or uses another incoming order type this year.
Again I'm sorry for the bad explanation, I'm trying my best (I understand myself very well)
Here is the expected result:
Expected Result
I marked in red the last year part and in green the current year part.
If you change the subquery to:
SELECT
iot.IncomingOrderTypeKey,
MAX(Sale_Revenue)
FROM [dwh01].[live].DimIncomingOrderType iot
GROUP BY iot.IncomingOrderTypeKey
then you can JOIN (not APPLY) directly on IncomingOrderTypeKey AND Sale_Revenue.
Try this:
USE dwh01;
DECLARE #CustomerKey varchar(6) = '157053'
, #ReportCurrencyId varchar(2) = 'LC'
, #CurrentYear int = YEAR(GETDATE())
, #TargetYear int = YEAR(GETDATE())-1
;
WITH FactsTable AS
(
SELECT
s.CustomerKey
, i.IncomingOrderTypeid
, [Sale_Revenue] = ISNULL(s.[Sale_Revenue] , 0)
, [Sale_GrossMarginTotal] = ISNULL(s.[Sale_GrossMarginTotal], 0)
, d.[Year]
FROM [dwh01].[live].[FactSales] s
inner join live.DimDate d on d.DateId = s.PostingDateKey
inner join live.DimIncomingOrderType i on i.IncomingOrderTypeKey = s.IncomingOrderTypeKey
where
s.CustomerKey = #CustomerKey
and s.ReportCurrencyId = #ReportCurrencyId
)
, OrderTypeTable
(
SELECT
c.CustomerKey
, c.BranchId
, c.CustomerId
, c.CustomerName
, c.SalesRepKey
, IncomingOrderType_LY = SUM(CASE WHEN y.[Year] = #TargetYear THEN y.IncomingOrderTypeId ELSE 0 END)
, [Sale_Revenue_LY] = SUM(CASE WHEN y.[Year] = #TargetYear THEN y.[Sale_Revenue] ELSE 0 END)
, [Sale_GrossMarginTotal_LY] = SUM(CASE WHEN y.[Year] = #TargetYear THEN y.[Sale_GrossMarginTotal] ELSE 0 END)
, IncomingOrderType_LY = SUM(CASE WHEN y.[Year] = #CurrentYear THEN y.IncomingOrderTypeId ELSE 0 END)
, [Sale_Revenue_CY] = SUM(CASE WHEN y.[Year] = #CurrentYear THEN y.[Sale_Revenue] ELSE 0 END)
, [Sale_GrossMarginTotal_CY] = SUM(CASE WHEN y.[Year] = #CurrentYear THEN y.[Sale_GrossMarginTotal] ELSE 0 END)
FROM live.DimCustomer c
left join FactsTable y on y.CustomerKey = c.CustomerKey
group by
c.CustomerKey
, c.BranchId
, c.CustomerId
, c.CustomerName
, y.IncomingOrderTypeId
, c.SalesRepKey
)
SELECT
O.BranchId
, R.SalesRepId
, R.SalesRepName
, O.CustomerId
, O.CustomerName
, O.Sale_Revenue_LY
, O.Sale_GrossMarginTotal_LY
, O.IncomingOrderType_LY
, O.Sale_Revenue_CY
, O..Sale_GrossMarginTotal_CY
, O.IncomingOrderType_CY
from OrderTypeTable O
join live.DimSalesRep R on R.SalesRepKey = O.SalesRepKey
order by
O.Sale_Revenue_CY desc
, O.Sale_Revenue_LY desc
, R.SalesRepId
The solution is with using row_number() function in the inner query of the first CTE:
(
select *, row_number() over (partition by x0.CustomerKey order by x0.Sale_Revenue desc) as rn
from
(
select fs.CustomerKey, iot.IncomingOrderTypeKey,
sum(fs.Sale_Revenue) as Sale_Revenue
FROM [dwh01].[live].DimIncomingOrderType iot
join live.FactSales fs
on iot.IncomingOrderTypeKey = fs.IncomingOrderTypeKey
join live.DimDate d
on d.DateId = fs.PostingDateKey
where d.[year] = #CurrentYear
GROUP BY fs.CustomerKey, iot.IncomingOrderTypeKey
) as x0
) as x1 on x1.CustomerKey = s.CustomerKey
The row_number() function gets only the first row from the result for each customer, and that is with the biggest sale revenue ( order by sale_revenue desc).

Pivoting to append the last 6 payments for 24 loans

I am building a query in Microsoft sql server where I want to find the active loans as well as some information on them. I have built out a common table expression that gives me the correct population. Now I need to get the last 6 payments starting from today. I have a another common table expression that gives all the payments and the payment data received but I am not sure how to pivot and append the last 6 payments such that I have something like this:
This is what the query and output looks like for the common table expression where I can get c1,...,c6.
SELECT Account,Total,CONVERT(datetime,DateRec) [Date Received]
FROM mars.dbo.vw_PaymentHistory PH
WHERE PH.SourceTyp not like '%fundin%' and PH.SourceTyp not like '%draw%'
which gives this (but much more):
Here is the whole query I am working from:
Declare #monthEnding date = '3/31/2020',
#monthStart date = '3/1/2020';
WITH Active_Loans as (
SELECT
la.Account,
la.LoanStatus,
la.PrinBal,
isnull(b.Amount, 0) [DUPB],
la.PrinBal + isnull(b.Amount, 0) [TotalUPB],
l.NoteOwner,
pt.[Partition],
l.paidoffdate,
la.[First Name],
la.[Last Name],
la.PmtPI,
la.PmtImpound,
la.NextDueDate,
la.MaturityDate,
la.NoteOwner as [Note Owner]
FROM MARS_DW..vw_vw_Loans_ArchiveEOM la
LEFT JOIN MARS_DW..vw_DUPBByLoan b on b.Account = la.Account
AND b.ArchiveDate = la.ArchiveDate
LEFT JOIN MARS..vw_Loans l on l.Account = la.Account
LEFT JOIN Portfolio_Analytics..partition_table pt on pt.Noteowner = l.NoteOwner
WHERE la.MonthEnding = #monthEnding
AND la.isActive = 1
AND la.PaidOffDate is null
AND la.LoanStatus NOT LIKE 'BK Payment Plan'
AND la.LoanStatus NOT LIKE 'Prelim'
AND la.LoanStatus NOT like 'trailing claims'
AND la.Account NOT IN (
SELECT account
FROM MARS..vw_Loans
WHERE servicexferdate <=
DATEADD(dd, - 1, DATEADD(mm, DATEDIFF(mm, 0, #monthStart) + 1, 0))
AND PaidOffDate BETWEEN #monthStart AND DATEADD(dd, - 1, DATEADD(mm, DATEDIFF(mm, 0, #monthStart) + 1, 0))
)
UNION
(
SELECT l.account
,la.LoanStatus
,la.PrinBal
,isnull(b.Amount, 0) [DUPB]
,la.PrinBal + isnull(b.Amount, 0) [TotalUPB]
,l.NoteOwner
,pt.[Partition]
,l.PaidOffDate
,la.[First Name]
,la.[Last Name]
,la.PmtPI
,la.PmtImpound
,la.NextDueDate
,la.MaturityDate
,la.NoteOwner as [Note Owner]
FROM MARS..vw_Loans l
LEFT JOIN MARS_DW..vw_vw_Loans_ArchiveEOM la on la.Account = l.Account
LEFT JOIN MARS_DW..vw_DUPBByLoan b on b.Account = la.Account
LEFT JOIN Portfolio_Analytics..partition_table pt on pt.Noteowner = l.NoteOwner
AND b.ArchiveDate = la.ArchiveDate
WHERE l.servicexferdate < #monthEnding
AND l.PaidOffDate > #monthEnding
AND la.MonthEnding = #monthEnding
AND la.LoanStatus NOT like 'trailing claims'
AND la.LoanStatus NOT like 'Inactive - REO/FC'
AND pt.[Partition] IS NOT NULL
)
)
,
payments as
(
SELECT Account,Total,CONVERT(datetime,DateRec) [Date Received]
FROM mars.dbo.vw_PaymentHistory PH
WHERE PH.SourceTyp not like '%fundin%' and PH.SourceTyp not like '%draw%'
)
SELECT
rptpop.Account
, rptpop.[First Name]
, rptpop.[Last Name]
, '$' + CONVERT (VARCHAR (12), rptpop.PmtPI+rptpop.PmtImpound, 1) as PITI
,'$' + CONVERT (VARCHAR (12), rptpop.TotalUPB, 1) as [Total UPB]
, CONVERT(VARCHAR(10),rptpop.NextDueDate,101) as [Next Due Date]
, CONVERT(VARCHAR(10),rptpop.MaturityDate,101) as [Maturity Date]
, rptpop.[Note Owner]
FROM Active_Loans as rptpop
LEFT JOIN payments as pmt on pmt.Account = rptpop.Account
WHERE
rptpop.Partition = 'GAEA'
AND rptpop.LoanStatus = 'Current'
AND rptpop.[Last Name] NOT LIKE '%CRE%'
AND pmt.[Date Received] BETWEEN #monthStart AND #monthEnding
EDIT:
Based on the answer below I was able to do this:
payments as
(
SELECT ROW_NUMBER() OVER(Partition By Account ORDER BY CONVERT(datetime,DateRec) DESC) AS [RowNumber], Total, Account
FROM mars.dbo.vw_PaymentHistory
)
,
get_payment1 as
(
SELECT * FROM payments
where RowNumber = 1
)
Which gives me numbers but what I do not understand is whether 1.) This is indeed correct and 2.) Assuming it is correct how do is it getting the most recent date? Perhaps its the order by clause?
I see a couple of way to solve the problem. I can share the approach using pseudo code.
Create Payments CTE , something like SELECT ROW_NUMBER() OVER(Partition By Account ORDER BY ReceivedDate DESC) . Then create 6 CTE's that use the above CTE with Row_Number 1 thru 6. Then simply use those using Left Join in your query, joining on Account#. This will add c1-c6 columns.
A second approach can be to use the same Payments CTE but instead of multiple CTEs, find a way to use UNPIVOT unpivot (Amount for Rows in (1,2,3,4,5,6) ) u;

Adding an additional Inner join with mutiple tables SQL

I'm wondering how to inner join customer name-(CUSTNAM) from table rm001 to this query & have it added to my SSRS Report. Could use help adding this. Thanks
I've tried adding after the "from" saleslineitems as an "and" but it broke the SSRS report.
use n
select distinct a.[SOP Number]
--, [Item Number]
, a.[Customer Number], a.[Created Date from Sales Transaction], a.[Primary Shipto Address Code from Sales Line Item]
, a.[City from Sales Transaction],
,c.city
,case
when b.CITY <> c.city then 'Cities Do Not Match'
when c.city = '' then 'Cities do not Match'
when isnull(c.city,'1') = '1' then 'Cities Do Not Match'
else ''
end as [validate cities]
,b.USERDEF1 as GP_F
, c.f_number as EZ_F
,case
when b.USERDEF1 <> c.f_number then 'Fs do not Match'
when b.USERDEF1 = '' then 'No F in GP'
else ''
end as [validate Fs]
, c.f_expiration
,case
when c.f_expiration <= getdate() then ' F EXPIRED '
when c.f_expiration <= DATEADD(d,15,getDate()) then 'F expiring soon'
--when c.f_expiration >= dateAdd(d,61,getdate()) then 'valid F Expiration'
else ''
end as [valid f date]
--,( select top(1) c.f_number from NBS_BoundBook..contacts where c.f_number = b.userdef1 order by c.uid desc )
--, a.*
from SalesLineItems a
inner join rm00102 b on a.[customer number] = b.CUSTNMBR and a.[Primary Shipto Address Code from Sales Line Item] = b.ADRSCODE
left join NBS_BoundBook..contacts c on Replace(Replace(ltrim(rtrim(b.USERDEF1)),CHAR(10),''),CHAR(13),'') =
( select top(1) Replace(Replace(ltrim(rtrim(c.f_number)),CHAR(10),''),CHAR(13),'') from NBS_BoundBook..contacts
where Replace(Replace(ltrim(rtrim(c.f_number)),CHAR(10),''),CHAR(13),'') = Replace(Replace(ltrim(rtrim(b.USERDEF1)),CHAR(10),''),CHAR(13),'')
and c.city= b.CITY order by c.uid desc )
where [sop type] = 'Order'
and [Created Date from Sales Transaction] >= dateAdd(d,-3, getDate())
and [Item Tracking Option] in ( 'Serial Numbers' )
order by a.[Customer Number]
Something like this should work:
.....
FROM SalesLineItems a
INNER JOIN rm00102 b
ON a.[customer number] = b.CUSTNMBR
AND a.[Primary Shipto Address Code from Sales Line Item] = b.ADRSCODE
INNER JOIN rm001 cust
ON cust.[customer number] = a.[customer number]
LEFT JOIN NBS_BoundBook..contacts c
....

SQL query multiplying SUM results when joining to multiple transaction tables

I'm developing a report which measures cash performance based on allocation and cancellation dates. To measure this I've queried a transactions sub query which pulls back all transactions and is joined on an account number and transaction from and to dates. This is then summed up at the top of the query.
All works fine when using one sub query however I'm now having to add an extra transactions sub query; 1 to calculate actual payments from the allocation date (to cancellation date or today if value is null) and the 2nd to calculate any cancelled payments from the allocation date + 14 days (to cancellation date or today if value is null).
The first sub query works perfectly but now I've added the second it's multiplying the summed value by 8. I've had this in the past when trying to query this table twice. (Not always by 8). Any ideas?
Thanks
The sums totalling these (TEST1 works fine, TEST2 not so much) and the sub queries:
SUM(CASE WHEN v1.[Transaction Date1] >= dateadd(DD, 1, EOMONTH(getdate(), -1))
THEN v1.[Payments] ELSE 0
END) AS TEST1,
SUM(CASE WHEN v2.[Transaction Date2] >= dateadd(DD, 1, EOMONTH(getdate(), -1))
THEN v2.[Payments2] ELSE 0
END) AS TEST2,
My code:
LEFT JOIN
(SELECT
[Account Number1], [Transaction Date1], SUM([Payments1]) AS [Payments]
FROM
(SELECT
ACCOUNTNO AS [Account Number1],
TRANDT AS [Transaction Date1],
CASE
WHEN TRANSACTIONTYPE = 'Credit'
THEN TRANAMT * -1
ELSE TRANAMT
END [Payments1]
FROM
TRANSACTIONS t WITH (NOLOCK)
JOIN
TRANSACTIONDETAILS td WITH (NOLOCK) ON td.TRANSACTIONID = t.TRANSACTIONS1
JOIN
TRANSACTIONS a WITH (NOLOCK) ON a.ID = TRANSACTIONS1
AND [TRANTYPE] LIKE '%PAY%'
AND [TRANAMT] <> 0
INNER JOIN
ACCOUNTS na WITH (NOLOCK) ON a.ACCOUNTID = ACCOUNTS1
WHERE
TRANSACTIONTYPE = 'Credit') v
GROUP BY
[Account Number1], [Transaction Date1]) v1 ON MAINT.[ACCNO] = v1.[Account Number1]
AND MAINT.[Allocation Date] <= v1.[Transaction Date1]
AND v1.[Transaction Date1] <= MAINT.[Transaction to date]
LEFT JOIN
(SELECT
[Account Number2], [Transaction Date2], SUM([Payments2]) AS [Payments2]
FROM
(SELECT
ACCOUNTNO AS [Account Number2],
TRANDT AS [Transaction Date2],
CASE
WHEN TRANSACTIONTYPE = 'Credit'
THEN TRANAMT * -1
ELSE TRANAMT
END [Payments2]
FROM
TRANSACTIONS t WITH (NOLOCK)
INNER JOIN
TRANSACTIONDETAILS td WITH (NOLOCK) ON td.TRANSACTIONID = t.TRANSACTIONS1
INNER JOIN
TRANSACTIONS a WITH (NOLOCK) ON a.ID = TRANSACTIONS1
AND [TRANTYPE] LIKE '%PAY%'
AND [TRANAMT] <> 0
INNER JOIN
ACCOUNTS na WITH (NOLOCK) ON a.ACCOUNTID = ACCOUNTS1
WHERE
TRANSACTIONTYPE = 'Debit') v
GROUP BY
[Account Number2], [Transaction Date2]) v2 ON MAINT.[ACCNO] = v2.[Account Number2]
AND DATEADD(DD,10,MAINT.[DCA Allocation Date]) <= v2.[Transaction Date2]
AND v2.[Transaction Date2] <= MAINT.[Transaction to date]
Since the inner most subselect is the same in both joins, you should put it in a WITH statement at the top and then just use that twice.
Like this:
WITH v_CTE
AS
(SELECT
ACCOUNTNO AS [Account Number2],
TRANDT AS [Transaction Date2],
CASE
WHEN TRANSACTIONTYPE = 'Credit'
THEN TRANAMT * -1
ELSE TRANAMT
END [Payments2]
FROM
TRANSACTIONS t WITH (NOLOCK)
INNER JOIN
TRANSACTIONDETAILS td WITH (NOLOCK) ON td.TRANSACTIONID = t.TRANSACTIONS1
INNER JOIN
TRANSACTIONS a WITH (NOLOCK) ON a.ID = TRANSACTIONS1
AND [TRANTYPE] LIKE '%PAY%'
AND [TRANAMT] <> 0
INNER JOIN
ACCOUNTS na WITH (NOLOCK) ON a.ACCOUNTID = ACCOUNTS1
WHERE
TRANSACTIONTYPE = 'Debit')
...
LEFT JOIN
(SELECT
[Account Number1], [Transaction Date1], SUM([Payments1]) AS [Payments]
FROM
v_CTE v
GROUP BY
[Account Number1], [Transaction Date1]) v1 ON MAINT.[ACCNO] = v1.[Account Number1]
AND MAINT.[Allocation Date] <= v1.[Transaction Date1]
AND v1.[Transaction Date1] <= MAINT.[Transaction to date]
LEFT JOIN
(SELECT
[Account Number2], [Transaction Date2], SUM([Payments2]) AS [Payments2]
FROM
v_CTE v
GROUP BY
[Account Number2], [Transaction Date2]) v2 ON MAINT.[ACCNO] = v2.[Account Number2]
AND DATEADD(DD,10,MAINT.[DCA Allocation Date]) <= v2.[Transaction Date2]
AND v2.[Transaction Date2] <= MAINT.[Transaction to date]

CASE Statement in query

I am trying to return a bunch of values in a table without causing "duplicate" outputs. I thought a CASE statement or derived table may help? Any input would be great.
Within the column Product_code there are the following values
(AFF,E,H,PD,PDM,PDRL,PDRM etc)
Here is my SQL:
SELECT DISTINCT
[Member Id] = c.master_customer_id,
[Full Name] = c.label_name,
[First Name] = c.first_name,
[Last Name] = c.last_name,
[Email] = ISNULL(c.primary_email_address,''),
[Annual Meeting] = MAX(ca.product_code)
CASE WHEN od.product_code IN (AFF,E,H,PD,PDM,PDRL,PDRM) then ??
--[Membership Type] = od.product_code
FROM order_detail od
INNER JOIN customer c
on c.master_customer_id = od.ship_master_customer_id
and c.sub_customer_id = od.ship_sub_customer_id
and od.subsystem = 'MBR'
INNER JOIN cus_activity ca
on ca.master_customer_id = c.master_customer_id
and ca.sub_customer_id = c.sub_customer_id
and ca.subsystem = 'MTG'
and ca.activity_subcode IN ('2012AM', '2011AM')
and ca.product_code IN ('2012AM','2011AM')
INNER JOIN cus_address caddr
on caddr.master_customer_id = c.master_customer_id
and caddr.sub_customer_id = c.sub_customer_id
INNER JOIN cus_address_detail caddrd
on caddrd.cus_address_id = caddr.cus_address_id
where c.customer_class_code NOT IN ('STAFF', 'TEST_MBR')
and c.customer_status_code = 'ACTIVE'
and c.primary_email_address IS NOT NULL
and ca.master_customer_id IN (select order_detail.ship_master_customer_id
from order_detail where order_detail.subsystem = 'MBR')
and caddrd.priority_seq = 0
and caddrd.address_status_code = 'GOOD'
and od.product_code in
( 'AFF','E','H', 'PD','PDM','PDRL','PDRM','PDRU','R',
'RM','RRL','RRM','RRU','S','SM','SRL','SRM','SRU','SU','SUM','SURL','SURM','SURU' )
and od.cycle_end_date >= '01/01/2011' and od.cycle_end_date <= '12/31/2012'
GROUP BY c.master_customer_id,c.label_name,
c.FIRST_NAME,c.LAST_NAME,c.primary_email_address,od.product_code,caddr.country_descr
order by c.master_customer_id
You are looking for a Cross-Tab result (also known as a Pivot table) based on a given customer. You want all possible membership status levels as a person could be multiple levels (per your example).
With the group by on the customer ID, everything will roll-up to the member. So, if there are multiple product codes, I have applied SUM() based on each individual "product_code" you wanted to consider.
Next, to help optimize your query, I would ensure your Order_Detail has an index on
( SubSystem, Product_Code, Cycle_End_Date, ship_master_customer_id )
I've slightly rewritten to better allow myself to follow what you were getting and the criteria related to each table. Hopefully it makes sense to what you started with.
SELECT
c.master_customer_id as [Member Id],
c.label_name as [Full Name],
c.first_name as [First Name],
c.last_name as [Last Name],
ISNULL(c.primary_email_address,'') as [Email],
MAX(ca.product_code) as [Annual Meeting],
SUM( CASE WHEN od.product_code = 'AFF' then 1 else 0 end ) as Membership_AFF,
SUM( CASE WHEN od.product_code = 'E' then 1 else 0 end ) as Membership_E,
SUM( CASE WHEN od.product_code = 'H' then 1 else 0 end ) as Membership_H,
SUM( CASE WHEN od.product_code = 'PD' then 1 else 0 end ) as Membership_PD,
SUM( CASE WHEN od.product_code = 'PDM' then 1 else 0 end ) as Membership_PDM,
SUM( CASE WHEN od.product_code = 'PDRL' then 1 else 0 end ) as Membership_PDRL,
SUM( CASE WHEN od.product_code = 'PDRM' then 1 else 0 end ) as Membership_PDRM
FROM
order_detail od
INNER JOIN customer c
on od.ship_master_customer_id = c.master_customer_id
and od.ship_sub_customer_id = c.sub_customer_id
and c.customer_class_code NOT IN ('STAFF', 'TEST_MBR')
and c.customer_status_code = 'ACTIVE'
and c.primary_email_address IS NOT NULL
INNER JOIN cus_activity ca
on od.ship_master_customer_id = ca.master_customer_id
and od.ship_sub_customer_id = ca.sub_customer_id
and ca.subsystem = 'MTG'
and ca.activity_subcode IN ('2012AM', '2011AM')
and ca.product_code IN ('2012AM','2011AM')
INNER JOIN cus_address caddr
on od.ship_master_customer_id = caddr.master_customer_id
and od.ship_sub_customer_id = caddr.sub_customer_id
INNER JOIN cus_address_detail caddrd
on caddr.cus_address_id = caddrd.cus_address_id
and caddrd.priority_seq = 0
and caddrd.address_status_code = 'GOOD'
WHERE
od.subsystem = 'MBR'
and od.product_code in ( 'AFF','E','H','PD','PDM','PDRL','PDRM','PDRU',
'R','RM','RRL','RRM','RRU','S','SM','SRL',
'SRM','SRU','SU','SUM','SURL','SURM','SURU' )
and od.cycle_end_date >= '01/01/2011'
and od.cycle_end_date <= '12/31/2012'
GROUP BY
od.ship_master_customer_id,
c.label_name,
c.FIRST_NAME,
c.LAST_NAME,
c.primary_email_address,
caddr.country_descr
order by
od.ship_master_customer_id