Grouping sets is not aggregating results - sql
I've only recently started using this function, so forgive this question if it is imbecilic.
I have an existing query, which I've realised could be helped with the use of this query to create additional group by groupings, akin to subtotals.
In this example, I am wanting to aggregate in a hierarchy like this:
Year > Month > Profit Centre > Date
An example of the results this query is bringing back
As you can see my grouping sets are returning zero.
My question is, why?
My query is below
SELECT
datepart(yyyy,overview.Date) as 'Year',
datepart(mm,overview.Date) as'Month',
overview.Date as 'Date',
overview.[Profit Centre],
overview.[Current
Year Group Bookings],
overview.[Previous Year Group Bookings],
overview.[Current Year Total Covers],
overview.[Previous Year Total Covers],
overview.[Large Group Count]
FROM
(
SELECT
DISTINCT
CONVERT(date,csd.tendered_date_time) as 'Date',
PCM.profit_center_name as 'Profit Centre',
PCD.profit_center_id,
(
SELECT count(csd2.num_covers)
FROM ig_Business..check_sales_detail csd2
INNER JOIN ig_Dimension..Profit_Center_Dimension PCD2 (NOLOCK) ON
PCD2.profit_center_dim_id = CSD2.profit_center_dim_id and PCD2.ent_id = 1
WHERE PCD2.profit_center_id = PCD.profit_center_id
AND CONVERT(date,CSD2.tendered_date_time) =
CONVERT(date,CSD.tendered_date_time)
AND CSD2.num_covers >=
(CASE
WHEN PCD.profit_center_id = '77' THEN '8'
WHEN PCD.profit_center_id = '13' THEN '10'
WHEN PCD.profit_center_id IN ('60','61','62','63','64','65') THEN '16'
WHEN PCD.profit_center_id = '14' THEN '10'
WHEN PCD.profit_center_id = '90' THEN '10'
WHEN PCD.profit_center_id = '98' THEN '8'
WHEN PCD.profit_center_id IN ('74','101') THEN '10'
WHEN PCD.profit_center_id = '194' THEN '10'
WHEN PCD.profit_center_id = '49' THEN '15'
WHEN PCD.profit_center_id IN ('20','21','22','200') THEN '8'
WHEN PCD.profit_center_id = '74' THEN '15'
WHEN PCD.profit_center_id = '26' THEN '10'
WHEN PCD.profit_center_id IN ('86','68') THEN '8'
WHEN PCD.profit_center_id IN ('40','41','42','43') THEN '8'
WHEN PCD.profit_center_id IN ('96','98','99') THEN '10'
WHEN PCD.profit_center_id = '57' THEN '10'
END)
) as 'Current Year Group Bookings',
(
SELECT count(csd2.num_covers)
FROM ig_Business..check_sales_detail csd2
INNER JOIN ig_Dimension..Profit_Center_Dimension PCD2 (NOLOCK) ON
PCD2.profit_center_dim_id = CSD2.profit_center_dim_id and PCD2.ent_id = 1
WHERE PCD2.profit_center_id = PCD.profit_center_id
AND CONVERT(date,CSD2.tendered_date_time) =
CONVERT(date,DATEADD(month,-12,CSD.tendered_date_time))
AND CSD2.num_covers >=
(CASE
WHEN PCD.profit_center_id = '77' THEN '8'
WHEN PCD.profit_center_id = '13' THEN '10'
WHEN PCD.profit_center_id IN ('60','61','62','63','64','65') THEN '16'
WHEN PCD.profit_center_id = '14' THEN '10'
WHEN PCD.profit_center_id = '90' THEN '10'
WHEN PCD.profit_center_id = '98' THEN '8'
WHEN PCD.profit_center_id IN ('74','101') THEN '10'
WHEN PCD.profit_center_id = '194' THEN '10'
WHEN PCD.profit_center_id = '49' THEN '15'
WHEN PCD.profit_center_id IN ('20','21','22','200') THEN '8'
WHEN PCD.profit_center_id = '74' THEN '15'
WHEN PCD.profit_center_id = '26' THEN '10'
WHEN PCD.profit_center_id IN ('86','68') THEN '8'
WHEN PCD.profit_center_id IN ('40','41','42','43') THEN '8'
WHEN PCD.profit_center_id IN ('96','98','99') THEN '10'
WHEN PCD.profit_center_id = '57' THEN '10'
END)
) as 'Previous Year Group Bookings',
(
SELECT ISNULL(SUM(csd2.num_covers),0)
FROM ig_Business..check_sales_detail csd2
INNER JOIN ig_Dimension..Profit_Center_Dimension PCD2 (NOLOCK) ON
PCD2.profit_center_dim_id = CSD2.profit_center_dim_id and PCD2.ent_id = 1
WHERE PCD2.profit_center_id = PCD.profit_center_id
AND CONVERT(date,CSD2.tendered_date_time) =
CONVERT(date,CSD.tendered_date_time)
AND CSD2.num_covers >=
(CASE
WHEN PCD.profit_center_id = '77' THEN '8'
WHEN PCD.profit_center_id = '13' THEN '10'
WHEN PCD.profit_center_id IN ('60','61','62','63','64','65') THEN '16'
WHEN PCD.profit_center_id = '14' THEN '10'
WHEN PCD.profit_center_id = '90' THEN '10'
WHEN PCD.profit_center_id = '98' THEN '8'
WHEN PCD.profit_center_id IN ('74','101') THEN '10'
WHEN PCD.profit_center_id = '194' THEN '10'
WHEN PCD.profit_center_id = '49' THEN '15'
WHEN PCD.profit_center_id IN ('20','21','22','200') THEN '8'
WHEN PCD.profit_center_id = '74' THEN '15'
WHEN PCD.profit_center_id = '26' THEN '10'
WHEN PCD.profit_center_id IN ('86','68') THEN '8'
WHEN PCD.profit_center_id IN ('40','41','42','43') THEN '8'
WHEN PCD.profit_center_id IN ('96','98','99') THEN '10'
WHEN PCD.profit_center_id = '57' THEN '10'
END)
) as 'Current Year Total Covers',
(
SELECT ISNULL(SUM(csd2.num_covers),0)
FROM ig_Business..check_sales_detail csd2
INNER JOIN ig_Dimension..Profit_Center_Dimension PCD2 (NOLOCK) ON
PCD2.profit_center_dim_id = CSD2.profit_center_dim_id and PCD2.ent_id = 1
WHERE PCD2.profit_center_id = PCD.profit_center_id
AND CONVERT(date,CSD2.tendered_date_time) =
CONVERT(date,DATEADD(month,-12,CSD.tendered_date_time))
AND CSD2.num_covers >=
(CASE
WHEN PCD.profit_center_id = '77' THEN '8'
WHEN PCD.profit_center_id = '13' THEN '10'
WHEN PCD.profit_center_id IN ('60','61','62','63','64','65') THEN '16'
WHEN PCD.profit_center_id = '14' THEN '10'
WHEN PCD.profit_center_id = '90' THEN '10'
WHEN PCD.profit_center_id = '98' THEN '8'
WHEN PCD.profit_center_id IN ('74','101') THEN '10'
WHEN PCD.profit_center_id = '194' THEN '10'
WHEN PCD.profit_center_id = '49' THEN '15'
WHEN PCD.profit_center_id IN ('20','21','22','200') THEN '8'
WHEN PCD.profit_center_id = '74' THEN '15'
WHEN PCD.profit_center_id = '26' THEN '10'
WHEN PCD.profit_center_id IN ('86','68') THEN '8'
WHEN PCD.profit_center_id IN ('40','41','42','43') THEN '8'
WHEN PCD.profit_center_id IN ('96','98','99') THEN '10'
WHEN PCD.profit_center_id = '57' THEN '10'
END)
) as 'Previous Year Total Covers',
(CASE
WHEN PCD.profit_center_id = '77' THEN '8'
WHEN PCD.profit_center_id = '13' THEN '10'
WHEN PCD.profit_center_id IN ('60','61','62','63','64','65') THEN '16'
WHEN PCD.profit_center_id = '14' THEN '10'
WHEN PCD.profit_center_id = '90' THEN '10'
WHEN PCD.profit_center_id = '98' THEN '8'
WHEN PCD.profit_center_id IN ('74','101') THEN '10'
WHEN PCD.profit_center_id = '194' THEN '10'
WHEN PCD.profit_center_id = '49' THEN '15'
WHEN PCD.profit_center_id IN ('20','21','22','200') THEN '8'
WHEN PCD.profit_center_id = '74' THEN '15'
WHEN PCD.profit_center_id = '26' THEN '10'
WHEN PCD.profit_center_id IN ('86','68') THEN '8'
WHEN PCD.profit_center_id IN ('40','41','42','43') THEN '8'
WHEN PCD.profit_center_id IN ('96','98','99') THEN '10'
WHEN PCD.profit_center_id = '57' THEN '10'
END) AS 'Large Group Count'
FROM ig_business..Check_Sales_Detail CSD (NOLOCK)
INNER JOIN ig_Dimension..Profit_Center_Dimension PCD (NOLOCK) ON
PCD.profit_center_dim_id = CSD.profit_center_dim_id and PCD.ent_id = 1
INNER JOIN it_cfg..Profit_Center_Master PCM (NOLOCK) ON PCM.profit_center_id
= PCD.profit_center_id and PCm.ent_id = 1
WHERE
(
(pcd.profit_center_id = '77' AND csd.num_covers > 8)
OR
(pcd.profit_center_id = '13' AND csd.num_covers >= 10)
OR
(pcd.profit_center_id IN ('60','61','62','63','64','65') AND
csd.num_covers > 16)
OR
(pcd.profit_center_id = 14 AND csd.num_covers >= 10)
OR
(pcd.profit_center_id = 90 AND csd.num_covers >= 10)
OR
(pcd.profit_center_id = 98 AND csd.num_covers >= 8)
OR
(pcd.profit_center_id IN ('74','101') AND csd.num_covers >= 10)
OR
(pcd.profit_center_id = '194' AND csd.num_covers >= 10)
OR
(pcd.profit_center_id = '49' AND csd.num_covers >= 15)
OR
(pcd.profit_center_id IN ('20','21','22','200') AND csd.num_covers >= 8)
OR
(pcd.profit_center_id = '74' AND csd.num_covers >= 15)
OR
(pcd.profit_center_id = '26' AND csd.num_covers >= 10)
OR
(pcd.profit_center_id IN ('86','68') AND csd.num_covers >= 8)
OR
(pcd.profit_center_id IN ('40','41','42','43') AND csd.num_covers >= 8)
OR
(pcd.profit_center_id IN ('96','98','99') AND csd.num_covers >= 10)
OR
(pcd.profit_center_id = '57' AND csd.num_covers >= 10)
)
AND
CSD.tendered_date_time > CONVERT(date,'2017-01-01') -- We only want
comparisons from today going forward, i.e. not historical
GROUP BY
GROUPING SETS
(
(csd.tendered_date_time, PCM.profit_center_name,PCD.profit_center_id),
(datepart(yyyy,csd.tendered_date_time),datepart(mm,csd.tendered_date_time),
pcm.profit_center_name),
()
)
) overview
ORDER BY overview.[Profit Centre] asc, CONVERT(date,overview.Date) asc
My question is, why (are the grouping sets zero)?
Because you are not using aggregate functions such as SUM() or COUNT() in a manner than can be summarised into sub-totals. You are using a set of "correlated subqueries" which do use COUNT() but by the time these are evaluated the outer query just sees those columns as data (not as aggregates).
example (untested of course):
WITH pcd AS (
SELECT *
FROM ig_Dimension..Profit_Center_Dimension pcd
WHERE (
OR (pcd.profit_center_id = '13' AND csd.num_covers >= 10)
OR (pcd.profit_center_id = 14 AND csd.num_covers >= 10) -- is it an integer? or not?
OR (pcd.profit_center_id = '26' AND csd.num_covers >= 10)
OR (pcd.profit_center_id = '49' AND csd.num_covers >= 15)
OR (pcd.profit_center_id = '57' AND csd.num_covers >= 10)
OR (pcd.profit_center_id = '74' AND csd.num_covers >= 15)
OR (pcd.profit_center_id = '77' AND csd.num_covers > 8)
OR (pcd.profit_center_id = 90 AND csd.num_covers >= 10) -- is it an integer? or not?
OR (pcd.profit_center_id = 98 AND csd.num_covers >= 8) -- is it an integer? or not?
OR (pcd.profit_center_id = '194' AND csd.num_covers >= 10)
OR (pcd.profit_center_id IN ('20', '21', '22', '200') AND csd.num_covers >= 8)
OR (pcd.profit_center_id IN ('40', '41', '42', '43') AND csd.num_covers >= 8)
OR (pcd.profit_center_id IN ('60', '61', '62', '63', '64', '65') AND csd.num_covers > 16)
OR (pcd.profit_center_id IN ('74', '101') AND csd.num_covers >= 10)
OR (pcd.profit_center_id IN ('86', '68') AND csd.num_covers >= 8)
OR (pcd.profit_center_id IN ('96', '98', '99') AND csd.num_covers >= 10)
)
AND pcd.ent_id = 1
)
SELECT
DATEPART(yyyy, csd.tendered_date_time) AS 'Year'
, DATEPART(mm, csd.tendered_date_time) AS 'Month'
, pcd.[Profit Centre]
, pcm.profit_center_name AS 'Profit Centre'
, pcd.profit_center_id
, COUNT(csd.num_covers)
FROM ig_business..Check_Sales_Detail csd
INNER JOIN pcd ON pcd.profit_center_dim_id = csd.profit_center_dim_id
INNER JOIN it_cfg..Profit_Center_Master pcm ON pcm.profit_center_id = pcd.profit_center_id
AND pcm.ent_id = 1
GROUP BY GROUPING SETS
( DATEPART(yyyy, csd.tendered_date_time) AS 'Year'
, DATEPART(mm, csd.tendered_date_time) AS 'Month'
, pcd.[Profit Centre]
, pcm.profit_center_name AS 'Profit Centre'
, pcd.profit_center_id
)
NOTE: you need to be careful about "implicit conversions", if pcd.profit_center_id is an integer then do NOT use '194', but if it is a varchar or similar then do not use integers. I also suggest you try to keep that where clause in some "order" so it is easier to read.
Related
SQL CASE and JOIN Query
I am writing a query using Join and CASE query on SQL but it iis not giving the desired result. If I try running the count command it works individually, and if I try the other command, its running individually, but if I combine them, they are not working fine. In this case, if I were to remove COUNT(CCD_METHOD_OPTION_DESC.OPTION_ID), it works but adding it as below doesn't work. SELECT COUNT(CCD_METHOD_OPTION_DESC.OPTION_ID) CASE when CCD_METHOD_OPTION_DESC.OPTION_ID = '1' then 'Option1' when CCD_METHOD_OPTION_DESC.OPTION_ID = '2' then 'Option2' when CCD_METHOD_OPTION_DESC.OPTION_ID = '3' then 'Option3' when CCD_METHOD_OPTION_DESC.OPTION_ID = '4' then 'Option4' when CCD_METHOD_OPTION_DESC.OPTION_ID = '5' then 'Option5' when CCD_METHOD_OPTION_DESC.OPTION_ID = '6' then 'Option6' when CCD_METHOD_OPTION_DESC.OPTION_ID = '7' then 'Option7' when CCD_METHOD_OPTION_DESC.OPTION_ID = '8' then 'Option8' when CCD_METHOD_OPTION_DESC.OPTION_ID = '9' then 'Option9' when CCD_METHOD_OPTION_DESC.OPTION_ID = '0' then 'Option0' else 'NoNumber' END AS Option_ID , METHOD_ID, CCD_METHOD_OPTION_DESC.CLIENT_ID, CCD_CALLS.DNIS, CCD_CALLS.ACCOUNT_NO , CCD_CALLS.LANG, CCD_CALLS.CCD_LAST_METHOD, CCD_CALLS.PERSON_ID , CCD_CALLS.ROUTE_CODE, CCD_CALLS.TRANSFER_TO, CCD_CALLS.CCD_END_CODE , CCD_CALLS.STARTDATETIME, CONVERT(char(10),CCD_CALLS.STARTDATETIME,101) as Date , CONVERT(char(20),CCD_CALLS.STARTDATETIME,108) as Interval_Time , CCD_CALLS.ENDDATETIME from CCD_METHOD_OPTION_DESC RIGHT JOIN CCD_CALLS ON CCD_CALLS.CLIENT_ID = CD_METHOD_OPTION_DESC.CLIENT_ID) Essentially, I am trying to get a count of each option such as How many times each options 0-9 was selected with other information
try this : SELECT COUNT(CCD_METHOD_OPTION_DESC.OPTION_ID) over(partition by CASE when CCD_METHOD_OPTION_DESC.OPTION_ID = '1' then 'Option1' when CCD_METHOD_OPTION_DESC.OPTION_ID = '2' then 'Option2' when CCD_METHOD_OPTION_DESC.OPTION_ID = '3' then 'Option3' when CCD_METHOD_OPTION_DESC.OPTION_ID = '4' then 'Option4' when CCD_METHOD_OPTION_DESC.OPTION_ID = '5' then 'Option5' when CCD_METHOD_OPTION_DESC.OPTION_ID = '6' then 'Option6' when CCD_METHOD_OPTION_DESC.OPTION_ID = '7' then 'Option7' when CCD_METHOD_OPTION_DESC.OPTION_ID = '8' then 'Option8' when CCD_METHOD_OPTION_DESC.OPTION_ID = '9' then 'Option9' when CCD_METHOD_OPTION_DESC.OPTION_ID = '0' then 'Option0' else 'NoNumber' END ) AS Option_ID_ct ,CASE when CCD_METHOD_OPTION_DESC.OPTION_ID = '1' then 'Option1' when CCD_METHOD_OPTION_DESC.OPTION_ID = '2' then 'Option2' when CCD_METHOD_OPTION_DESC.OPTION_ID = '3' then 'Option3' when CCD_METHOD_OPTION_DESC.OPTION_ID = '4' then 'Option4' when CCD_METHOD_OPTION_DESC.OPTION_ID = '5' then 'Option5' when CCD_METHOD_OPTION_DESC.OPTION_ID = '6' then 'Option6' when CCD_METHOD_OPTION_DESC.OPTION_ID = '7' then 'Option7' when CCD_METHOD_OPTION_DESC.OPTION_ID = '8' then 'Option8' when CCD_METHOD_OPTION_DESC.OPTION_ID = '9' then 'Option9' when CCD_METHOD_OPTION_DESC.OPTION_ID = '0' then 'Option0' else 'NoNumber' END AS Option_ID , METHOD_ID, CCD_METHOD_OPTION_DESC.CLIENT_ID, CCD_CALLS.DNIS, CCD_CALLS.ACCOUNT_NO , CCD_CALLS.LANG, CCD_CALLS.CCD_LAST_METHOD, CCD_CALLS.PERSON_ID , CCD_CALLS.ROUTE_CODE, CCD_CALLS.TRANSFER_TO, CCD_CALLS.CCD_END_CODE , CCD_CALLS.STARTDATETIME, CONVERT(char(10),CCD_CALLS.STARTDATETIME,101) as Date , CONVERT(char(20),CCD_CALLS.STARTDATETIME,108) as Interval_Time , CCD_CALLS.ENDDATETIME from CCD_METHOD_OPTION_DESC RIGHT JOIN CCD_CALLS ON CCD_CALLS.CLIENT_ID = CD_METHOD_OPTION_DESC.CLIENT_ID
solution using WITH clause... WITH count_options (count, OPTION_ID) AS ( SELECT COUNT(*) as count CCD_METHOD_OPTION_DESC.OPTION_ID as OPTION_ID from CCD_METHOD_OPTION_DESC group by CCD_METHOD_OPTION_DESC.OPTION_ID ) SELECT count_options.COUNT, CASE when CCD_METHOD_OPTION_DESC.OPTION_ID = '1' then 'Option1' when CCD_METHOD_OPTION_DESC.OPTION_ID = '2' then 'Option2' when CCD_METHOD_OPTION_DESC.OPTION_ID = '3' then 'Option3' when CCD_METHOD_OPTION_DESC.OPTION_ID = '4' then 'Option4' when CCD_METHOD_OPTION_DESC.OPTION_ID = '5' then 'Option5' when CCD_METHOD_OPTION_DESC.OPTION_ID = '6' then 'Option6' when CCD_METHOD_OPTION_DESC.OPTION_ID = '7' then 'Option7' when CCD_METHOD_OPTION_DESC.OPTION_ID = '8' then 'Option8' when CCD_METHOD_OPTION_DESC.OPTION_ID = '9' then 'Option9' when CCD_METHOD_OPTION_DESC.OPTION_ID = '0' then 'Option0' else 'NoNumber' END AS Option_ID , METHOD_ID, CCD_METHOD_OPTION_DESC.CLIENT_ID, CCD_CALLS.DNIS, CCD_CALLS.ACCOUNT_NO , CCD_CALLS.LANG, CCD_CALLS.CCD_LAST_METHOD, CCD_CALLS.PERSON_ID , CCD_CALLS.ROUTE_CODE, CCD_CALLS.TRANSFER_TO, CCD_CALLS.CCD_END_CODE , CCD_CALLS.STARTDATETIME, CONVERT(char(10),CCD_CALLS.STARTDATETIME,101) as Date , CONVERT(char(20),CCD_CALLS.STARTDATETIME,108) as Interval_Time , CCD_CALLS.ENDDATETIME from CCD_METHOD_OPTION_DESC RIGHT JOIN CCD_CALLS ON CCD_CALLS.CLIENT_ID = CD_METHOD_OPTION_DESC.CLIENT_ID INNER JOIN count_options ON count_options.OPTION_ID = CCD_METHOD_OPTION_DESC.OPTION_ID;
TSQL convert list of IP addresses to CIDR notation
Given a table with the following IP Addresses IPAddress ----------- 192.168.1.1 192.168.1.2 192.168.1.3 192.168.1.4 192.168.1.5 192.168.1.6 192.168.1.7 192.168.1.8 I'm looking for the following output Output --------------- 192.168.1.0/29 192.168.1.8/32 The closest I've come was with this: SELECT SUBSTRING(IPAddress, 1, LEN(IPAddress) - CHARINDEX('.',REVERSE(IPAddress))), COUNT(*) FROM IP GROUP BY SUBSTRING(IPAddress, 1, LEN(IPAddress) - CHARINDEX('.',REVERSE(IPAddress))) But that only gets me the subnet and # of address. Not sure how to take the next step.
You will need the subnet-mask in order to know the correct amount of host bits for your notation. This will give you CIDR: DECLARE #IPADDRESS VARCHAR(15) = '192.168.1.1' ,#NETMASK VARCHAR(15) = '255.255.255.0' ,#NETWORKBITS VARCHAR(3) SET #NETWORKBITS = CASE WHEN #NETMASK = '255.0.0.0' THEN '8' WHEN #NETMASK = '255.128.0.0' THEN '9' WHEN #NETMASK = '255.192.0.0' THEN '10' WHEN #NETMASK = '255.224.0.0' THEN '11' WHEN #NETMASK = '255.240.0.0' THEN '12' WHEN #NETMASK = '255.248.0.0' THEN '13' WHEN #NETMASK = '255.252.0.0' THEN '14' WHEN #NETMASK = '255.254.0.0' THEN '15' WHEN #NETMASK = '255.255.0.0' THEN '16' WHEN #NETMASK = '255.255.128.0' THEN '17' WHEN #NETMASK = '255.255.192.0' THEN '18' WHEN #NETMASK = '255.255.224.0' THEN '19' WHEN #NETMASK = '255.255.240.0' THEN '20' WHEN #NETMASK = '255.255.248.0' THEN '21' WHEN #NETMASK = '255.255.252.0' THEN '22' WHEN #NETMASK = '255.255.254.0' THEN '23' WHEN #NETMASK = '255.255.255.0' THEN '24' WHEN #NETMASK = '255.255.255.128' THEN '25' WHEN #NETMASK = '255.255.255.192' THEN '26' WHEN #NETMASK = '255.255.255.224' THEN '27' WHEN #NETMASK = '255.255.255.240' THEN '28' WHEN #NETMASK = '255.255.255.248' THEN '29' WHEN #NETMASK = '255.255.255.252' THEN '30' WHEN #NETMASK = '255.255.255.254' THEN '31' WHEN #NETMASK = '255.255.255.255' THEN '32' END PRINT #IPADDRESS + '/' #NETWORKBITS
Is it better to JOIN using OR in the join condition or to use multiple JOINS
I'm trying to flag tickets based on whether they indicate a certain event has occurred. The issue I'm running into is that the particular value(s) that indicate such a condition occurred could be in any 1 of 25 fields on the ticket and my current logic takes quite a while to complete (generally >45min) if it completes at all (our DBAs ocassionally kill it for taking too much CPU or having too high a PJI). Currently I'm using the below to try and flag the tickets: CREATE VOLATILE TABLE --DROP TABLE FCT AS ( SELECT I_FCT.Ticket_Nbr , I_FCT.Plan_Dim_CK , I_FCT.S_DATE , I_FCT.E_DATE , CASE WHEN I_FCT.Event1_CK = AD.Event_CK THEN '1' WHEN I_FCT.Event2_CK = AD.Event_CK THEN '2' WHEN I_FCT.Event3_CK = AD.Event_CK THEN '3' WHEN I_FCT.Event4_CK = AD.Event_CK THEN '4' WHEN I_FCT.Event5_CK = AD.Event_CK THEN '5' WHEN I_FCT.Event6_CK = AD.Event_CK THEN '6' WHEN I_FCT.Event7_CK = AD.Event_CK THEN '7' WHEN I_FCT.Event8_CK = AD.Event_CK THEN '8' WHEN I_FCT.Event9_CK = AD.Event_CK THEN '9' WHEN I_FCT.Event10_CK = AD.Event_CK THEN '10' WHEN I_FCT.Event11_CK = AD.Event_CK THEN '11' WHEN I_FCT.Event12_CK = AD.Event_CK THEN '12' WHEN I_FCT.Event13_CK = AD.Event_CK THEN '13' WHEN I_FCT.Event14_CK = AD.Event_CK THEN '14' WHEN I_FCT.Event15_CK = AD.Event_CK THEN '15' /*WHEN I_FCT.Event16_CK = AD.Event_CK THEN '16' WHEN I_FCT.Event17_CK = AD.Event_CK THEN '17' WHEN I_FCT.Event18_CK = AD.Event_CK THEN '18' WHEN I_FCT.Event19_CK = AD.Event_CK THEN '19' WHEN I_FCT.Event20_CK = AD.Event_CK THEN '20' WHEN I_FCT.Event21_CK = AD.Event_CK THEN '21' WHEN I_FCT.Event22_CK = AD.Event_CK THEN '22' WHEN I_FCT.Event23_CK = AD.Event_CK THEN '23' WHEN I_FCT.Event24_CK = AD.Event_CK THEN '24' WHEN I_FCT.Event25_CK = AD.Event_CK THEN '25'*/ ELSE NULL END AS AOD_Event FROM I_FCT LEFT JOIN AOD_CKS AS AD ON (AD.Event_CK = I_FCT.Event1_CK OR AD.Event_CK = I_FCT.Event2_CK OR AD.Event_CK = I_FCT.Event3_CK OR AD.Event_CK = I_FCT.Event4_CK OR AD.Event_CK = I_FCT.Event5_CK OR AD.Event_CK = I_FCT.Event6_CK OR AD.Event_CK = I_FCT.Event7_CK OR AD.Event_CK = I_FCT.Event8_CK OR AD.Event_CK = I_FCT.Event9_CK OR AD.Event_CK = I_FCT.Event10_CK OR AD.Event_CK = I_FCT.Event11_CK OR AD.Event_CK = I_FCT.Event12_CK OR AD.Event_CK = I_FCT.Event13_CK OR AD.Event_CK = I_FCT.Event14_CK OR AD.Event_CK = I_FCT.Event15_CK /*OR AD.Event_CK = I_FCT.Event16_CK OR AD.Event_CK = I_FCT.Event17_CK OR AD.Event_CK = I_FCT.Event18_CK OR AD.Event_CK = I_FCT.Event19_CK OR AD.Event_CK = I_FCT.Event20_CK OR AD.Event_CK = I_FCT.Event21_CK OR AD.Event_CK = I_FCT.Event22_CK OR AD.Event_CK = I_FCT.Event23_CK OR AD.Event_CK = I_FCT.Event24_CK OR AD.Event_CK = I_FCT.Event25_CK*/ ) ) WITH DATA PRIMARY INDEX (Ticket_Nbr) ON COMMIT PRESERVE ROWS; So my question is whether it would be better to switch to JOINing once per Event CK (which is a key value by the way & is the index on AOD_CKS)? Or should I go a little less verbose & try splitting up the work (i.e. join once for fields 1-6, another table for 7-13, etc.) & then JOIN those 4 tables together? Any help is much appreciated!
I ended up splitting the JOIN into 3 pieces and then merging the data as follows: ---------------------------------------------------------------------------- -- FLAG ADDICTION CLAIMS ---------------------------------------------------------------------------- CREATE VOLATILE TABLE --DROP TABLE I_FCT_1 AS ( SELECT I_FCT.Claim_Nbr , I_FCT.Plan_Dim_CK , CASE WHEN I_FCT.Diag1_CK = AD.Diag_CK THEN '1' WHEN I_FCT.Diag2_CK = AD.Diag_CK THEN '2' WHEN I_FCT.Diag3_CK = AD.Diag_CK THEN '3' WHEN I_FCT.Diag4_CK = AD.Diag_CK THEN '4' WHEN I_FCT.Diag5_CK = AD.Diag_CK THEN '5' WHEN I_FCT.Diag6_CK = AD.Diag_CK THEN '6' WHEN I_FCT.Diag7_CK = AD.Diag_CK THEN '7' WHEN I_FCT.Diag8_CK = AD.Diag_CK THEN '8' ELSE NULL END AS AOD_Diag FROM I_FCT LEFT JOIN ADD_CKS AS AD ON (AD.Diag_CK = I_FCT.Diag1_CK OR AD.Diag_CK = I_FCT.Diag2_CK OR AD.Diag_CK = I_FCT.Diag3_CK OR AD.Diag_CK = I_FCT.Diag4_CK OR AD.Diag_CK = I_FCT.Diag5_CK OR AD.Diag_CK = I_FCT.Diag6_CK OR AD.Diag_CK = I_FCT.Diag7_CK OR AD.Diag_CK = I_FCT.Diag8_CK ) ) WITH DATA PRIMARY INDEX (Claim_Nbr) ON COMMIT PRESERVE ROWS; ---------------------------------------------------------------------------- CREATE VOLATILE TABLE --DROP TABLE I_FCT_2 AS ( SELECT I_FCT.Claim_Nbr , I_FCT.Plan_Dim_CK , CASE WHEN I_FCT.Diag9_CK = AD.Diag_CK THEN '9' WHEN I_FCT.Diag10_CK = AD.Diag_CK THEN '10' WHEN I_FCT.Diag11_CK = AD.Diag_CK THEN '11' WHEN I_FCT.Diag12_CK = AD.Diag_CK THEN '12' WHEN I_FCT.Diag13_CK = AD.Diag_CK THEN '13' WHEN I_FCT.Diag14_CK = AD.Diag_CK THEN '14' WHEN I_FCT.Diag15_CK = AD.Diag_CK THEN '15' WHEN I_FCT.Diag16_CK = AD.Diag_CK THEN '16' ELSE NULL END AS AOD_Diag FROM I_FCT LEFT JOIN ADD_CKS AS AD ON (AD.Diag_CK = I_FCT.Diag9_CK OR AD.Diag_CK = I_FCT.Diag10_CK OR AD.Diag_CK = I_FCT.Diag11_CK OR AD.Diag_CK = I_FCT.Diag12_CK OR AD.Diag_CK = I_FCT.Diag13_CK OR AD.Diag_CK = I_FCT.Diag14_CK OR AD.Diag_CK = I_FCT.Diag15_CK OR AD.Diag_CK = I_FCT.Diag16_CK ) ) WITH DATA PRIMARY INDEX (Claim_Nbr) ON COMMIT PRESERVE ROWS; ---------------------------------------------------------------------------- CREATE VOLATILE TABLE --DROP TABLE I_FCT_3 AS ( SELECT I_FCT.Claim_Nbr , I_FCT.Plan_Dim_CK , CASE WHEN I_FCT.Diag17_CK = AD.Diag_CK THEN '17' WHEN I_FCT.Diag18_CK = AD.Diag_CK THEN '18' WHEN I_FCT.Diag19_CK = AD.Diag_CK THEN '19' WHEN I_FCT.Diag20_CK = AD.Diag_CK THEN '20' WHEN I_FCT.Diag21_CK = AD.Diag_CK THEN '21' WHEN I_FCT.Diag22_CK = AD.Diag_CK THEN '22' WHEN I_FCT.Diag23_CK = AD.Diag_CK THEN '23' WHEN I_FCT.Diag24_CK = AD.Diag_CK THEN '24' WHEN I_FCT.Diag25_CK = AD.Diag_CK THEN '25' ELSE NULL END AS AOD_Diag FROM I_FCT LEFT JOIN ADD_CKS AS AD ON (AD.Diag_CK = I_FCT.Diag17_CK OR AD.Diag_CK = I_FCT.Diag18_CK OR AD.Diag_CK = I_FCT.Diag19_CK OR AD.Diag_CK = I_FCT.Diag20_CK OR AD.Diag_CK = I_FCT.Diag21_CK OR AD.Diag_CK = I_FCT.Diag22_CK OR AD.Diag_CK = I_FCT.Diag23_CK OR AD.Diag_CK = I_FCT.Diag24_CK OR AD.Diag_CK = I_FCT.Diag25_CK ) ) WITH DATA PRIMARY INDEX (Claim_Nbr) ON COMMIT PRESERVE ROWS; --------------------------------------------------------------------------- CREATE VOLATILE TABLE --DROP TABLE FCT AS ( SELECT I_FCT.Claim_Nbr , I_FCT.Plan_Dim_CK , I_FCT.ADMISSION_DATE , I_FCT.DISCHARGE_DATE , I_FCT.ADMISSION_DATE_DIM_CK , I_FCT.Proc3_CK , I_FCT.Proc4_CK , I_FCT.Proc5_CK , I_FCT.Proc6_CK , I_FCT.Proc7_CK , I_FCT.Bill_Type , CASE WHEN C1.AOD_Diag IS NOT NULL THEN C1.AOD_Diag WHEN C2.AOD_Diag IS NOT NULL THEN C2.AOD_Diag WHEN C3.AOD_Diag IS NOT NULL THEN C3.AOD_Diag ELSE NULL END AS AOD_Diag FROM I_FCT JOIN I_FCT_1 AS C1 ON C1.Claim_Nbr = I_FCT.Claim_Nbr AND C1.Plan_Dim_CK = I_FCT.Plan_Dim_CK JOIN I_FCT_2 AS C2 ON I_FCT.Claim_Nbr = C2.Claim_Nbr AND I_FCT.Plan_Dim_CK = C2.Plan_Dim_CK JOIN I_FCT_3 AS C3 ON I_FCT.Claim_Nbr = C3.Claim_Nbr AND I_FCT.Plan_Dim_CK = C3.Plan_Dim_CK ) WITH DATA PRIMARY INDEX (Claim_Nbr) ON COMMIT PRESERVE ROWS;
SQL - how to consolidate Or statements
There must be a better way to write the query below, if you have any suggestions please let me know. SELECT * FROM [eSDR_Full].[dbo].[course_register] WHERE broad_field_code = '08' AND narrow_field_code = '05' AND detail_field_code = '05' AND end_month is null AND disabled <> 'Y' OR broad_field_code = '08' AND narrow_field_code = '05' AND detail_field_code = '05' AND end_month > '201512' AND disabled <> 'Y' OR broad_field_code = '08' AND narrow_field_code = '05' AND detail_field_code = '05' AND end_month is null AND disabled is null OR broad_field_code = '08' AND narrow_field_code = '05' AND detail_field_code = '05' AND end_month > '201512' AND disabled is null ORDER BY end_month DESC
First refactoring: SELECT * FROM [eSDR_Full].[dbo].[course_register] Where (broad_field_code = '08' and narrow_field_code = '05' and detail_field_code = '05') and ( (end_month is null and disabled <> 'Y') or (end_month > '201512' and disabled <> 'Y') or (end_month is null and disabled is null) or (end_month > '201512' and disabled is null)) order by end_month desc This makes it clear that you have a common prefix to all the conditions. Second refactoring takes advantage of other commonalities: SELECT * FROM [eSDR_Full].[dbo].[course_register] Where (broad_field_code = '08' and narrow_field_code = '05' and detail_field_code = '05') and (end_month is null or end_month > '201512') and (disabled is null or disabled <> 'Y') order by end_month desc Now it's clear that we just have a series of stacked ANDs based on simple conditions of one column each, so we can do this: SELECT * FROM [eSDR_Full].[dbo].[course_register] Where broad_field_code = '08' and narrow_field_code = '05' and detail_field_code = '05' and coalesce(end_month, '999999') > '201512' and coalesce(disabled, 'N') <> 'Y') order by end_month desc
This should work: SELECT * FROM [eSDR_Full].[dbo].[course_register] WHERE broad_field_code = '08' AND narrow_field_code = '05' AND detail_field_code = '05' AND (end_month IS NULL OR end_month > '201512') AND ISNULL(disabled,'') != 'Y' ORDER BY end_month DESC
SQL Subquery all data from same table
I have a table where I would like to have one field (account) always shown then subqueries for counts or sums with criteria. Example: select ndhist_acct_nbr, (select count(ndhist_acct_nbr) from dbo.nd_history where ndhist_type = '30' and ndhist_rsn = '0' and ndhist_trcd = 'NF*' and ndhist_ref_type = '0' and ndhist_dt >= '03/01/2013') as NSF_TOTAL, (select sum(ndhist_amt) from dbo.nd_history where ndhist_type = '30' and ndhist_rsn = '98' and ndhist_trcd = 'TW0' and ndhist_ref_type = '11' and ndhist_dt >= '03/01/2013') as SIG_SPEND, (select count(ndhist_acct_nbr) from dbo.nd_history where ndhist_type = '30' and ndhist_rsn = '23' and ndhist_trcd = 'TW0' and ndhist_ref_type = '11' and ndhist_dt >= '03/01/2013') as PIN_TRANS, (select count(ndhist_acct_nbr) from dbo.nd_history where ndhist_type = '30' and ndhist_rsn = '21' and ndhist_trcd = 'SC*' and ndhist_ref_type = '0' and ndhist_dt >= '03/01/2013') as FOREIGN_AMT_FEE from dbo.nd_history group by ndhist_acct_nbr The problem is the results - all of the account numbers show up but the counts/sum fields all repeat the data. Any help would be awesome!
Your subqueries are standalone - they don't depend on ndhist_acct_nbr field in any way, so the result is always the same. Besides, this technique (using this many subqueries for every row of output) is a bad idea. You should simplify the query, and instead of count distinct and subqueries, make sum(case when ... clauses.
Try: select ndhist_acct_nbr, count(case when ndhist_type = '30' and ndhist_rsn = '0' and ndhist_trcd = 'NF*' and ndhist_ref_type = '0' and ndhist_dt >= '03/01/2013' then ndhist_acct_nbr end) as NSF_TOTAL, sum(case when ndhist_type = '30' and ndhist_rsn = '98' and ndhist_trcd = 'TW0' and ndhist_ref_type = '11' and ndhist_dt >= '03/01/2013' then ndhist_amt end) as SIG_SPEND, count(case when ndhist_type = '30' and ndhist_rsn = '23' and ndhist_trcd = 'TW0' and ndhist_ref_type = '11' and ndhist_dt >= '03/01/2013' then ndhist_acct_nbr end) as PIN_TRANS, count(case when ndhist_type = '30' and ndhist_rsn = '21' and ndhist_trcd = 'SC*' and ndhist_ref_type = '0' and ndhist_dt >= '03/01/2013' then ndhist_acct_nbr end) as FOREIGN_AMT_FEE from dbo.nd_history group by ndhist_acct_nbr You can use derived columns from the results by putting the whole query inside an inline query and then selecting from it - like so: select sq.*, NSF_TOTAL*5 + SIG_SPEND*0.10 + PIN_TRANS*0.05 + FOREIGN_ATM_FEE as TOTAL_INCOME from (select ndhist_acct_nbr, count(case when ndhist_type = '30' and ndhist_rsn = '0' and ndhist_trcd = 'NF*' and ndhist_ref_type = '0' and ndhist_dt >= '03/01/2013' then ndhist_acct_nbr end) as NSF_TOTAL, sum(case when ndhist_type = '30' and ndhist_rsn = '98' and ndhist_trcd = 'TW0' and ndhist_ref_type = '11' and ndhist_dt >= '03/01/2013' then ndhist_amt end) as SIG_SPEND, count(case when ndhist_type = '30' and ndhist_rsn = '23' and ndhist_trcd = 'TW0' and ndhist_ref_type = '11' and ndhist_dt >= '03/01/2013' then ndhist_acct_nbr end) as PIN_TRANS, count(case when ndhist_type = '30' and ndhist_rsn = '21' and ndhist_trcd = 'SC*' and ndhist_ref_type = '0' and ndhist_dt >= '03/01/2013' then ndhist_acct_nbr end) as FOREIGN_AMT_FEE from dbo.nd_history group by ndhist_acct_nbr) sq This could be done more elegantly via a CTE if you are using a RDBMS (such as Oracle, PostgreSQL or SQLServer) that supports CTEs.