SQL Server define a group using a name list - sql-server

I have a simple query that counts different types of tickets by departments.
There are 5 departments. The query currently groups by dept.
SELECT
Dept_Name, COUNT(vsrv.TicketNbr) AS TotalTicketsSubmitted,
SUM(CASE WHEN vsrv.Closed_Flag = 1 THEN 1 ELSE 0 END) AS TotalTicketsClosed,
SUM(CASE WHEN vsrv.Closed_Flag = 0 THEN 1 ELSE 0 END) AS TotalOpenTickets
FROM
v_rpt_service vsrv
LEFT OUTER JOIN
v_rpt_SurveysByTicket vsrvy ON vsrv.TicketNbr = Vsrvy.SR_Service_RecID
WHERE
Dept_Name IN ('Application', 'Support', 'Service', 'Development', 'IT')
GROUP BY
Dept_Name
What I need is to do is group the ticket counts so Group1 is just 'Application' and Group2 is the rest of the departments.
Is there a way to define the groups by the Dept_Name?
Something like this if possible...
SELECT
Dept_Name, COUNT(vsrv.TicketNbr) AS TotalTicketsSubmitted,
SUM(CASE WHEN vsrv.Closed_Flag = 1 THEN 1 ELSE 0 END) AS TotalTicketsClosed,
SUM(CASE WHEN vsrv.Closed_Flag = 0 THEN 1 ELSE 0 END) AS TotalOpenTickets
FROM
v_rpt_service vsrv
LEFT OUTER JOIN
v_rpt_SurveysByTicket vsrvy ON vsrv.TicketNbr = Vsrvy.SR_Service_RecID
WHERE
Dept_Name IN ('Application', 'Support', 'Service', 'Development', 'IT')
GROUP BY GROUPING SETS
((Dept_Name), ('Application'), ('Support', 'Service', 'Development', 'IT'))

You can use grouping for this. Something like this should work for you.
SELECT CASE WHEN Dept_Name = 'Application' then Dept_Name else 'Group2' end as DepartmentName
, COUNT(vsrv.TicketNbr) AS TotalTicketsSubmitted
, SUM(CASE WHEN vsrv.Closed_Flag = 1 THEN 1 ELSE 0 END) AS TotalTicketsClosed
, SUM(CASE WHEN vsrv.Closed_Flag = 0 THEN 1 ELSE 0 END) AS TotalOpenTickets
FROM v_rpt_service vsrv LEFT OUTER JOIN v_rpt_SurveysByTicket vsrvy ON vsrv.TicketNbr = Vsrvy.SR_Service_RecID
WHERE Dept_Name in ('Application', 'Support', 'Service', 'Development', 'IT')
GROUP BY CASE WHEN Dept_Name = 'Application' then Dept_Name else 'Group2' end

Something like this might be helpful for you. I assumed the DEPT_NAME column is from v_rpt_service. If not replace it with v_rpt_SurveysByTicket
SELECT Dept_Name, COUNT(vsrv.TicketNbr) AS TotalTicketsSubmitted,
SUM(CASE WHEN vsrv.Closed_Flag = 1 THEN 1 ELSE 0 END) AS TotalTicketsClosed,
SUM(CASE WHEN vsrv.Closed_Flag = 0 THEN 1 ELSE 0 END) AS TotalOpenTickets
FROM (
Select v_rpt_service.* -- all fields other than Dept_Name
, CASE Dept_Name
WHEN 'Application' THEN 'Group 1'
ELSE 'Group 2'
END AS Dept_Name
FROM v_rpt_service
) vsrv
LEFT OUTER JOIN v_rpt_SurveysByTicket vsrvy ON vsrv.TicketNbr = Vsrvy.SR_Service_RecID
WHERE Dept_Name in ('Application', 'Support', 'Service', 'Development', 'IT')
GROUP BY Dept_Name

Related

SQL Server - Query with MAX(CASE ..) and GROUP BY runs too long

I added to my query max() and group by to exclude duplicates and now it's running very long, 56 minutes.
But before adding max() and group by it was running 7-8 min. It's ok, I'm using aggregate view in join and it takes time.
Without max() and group by I had duplicates of customers who opted-in and not opted-in. Where I wanted just to put value "1" if I see that customer has OptIn as "1".
Here is my code:
WITH
cteURC AS (
SELECT
distinct scvid
,MAX(CASE WHEN who = 'urc' AND OptIn = '1' THEN 1 ELSE 0 END) AS URC_OptIn
FROM
scv.OptIn
where who = 'urc'
),
cteSponsor AS (
SELECT
distinct scvid
,MAX(CASE WHEN who = 'sponsor/3rd party' AND OptIn = '1' THEN 1 ELSE 0 END) AS Partner_OptIn
FROM
scv.OptIn
where who = 'sponsor/3rd party'
GROUP BY scvid
),
cteLeinster AS (
SELECT
distinct scvid
,MAX(CASE WHEN who = 'leinster rugby' AND OptIn = '1' THEN 1 ELSE 0 END) AS Leinster_OptIn
FROM
scv.OptIn
where who = 'leinster rugby'
)
SELECT distinct(c.[ScvId])
,Title
,FirstName
,LastName
,EmailAddress
,DateOfBirth
,Address1
,City
,Telephone
,Gender
,URC_OptIn
,Partner_OptIn
,Leinster_OptIn
,MAX(CASE WHEN c.ScvId = T.ScvId AND ProductId = '2019' THEN 1 ELSE 0 END) AS FinalTicketPurchaser_2019
,MAX(CASE WHEN c.ScvId = T.ScvId AND ProductId = '2018' THEN 1 ELSE 0 END) AS FinalTicketPurchaser_2018
FROM scv.vwCustomer c
LEFT JOIN cteURC U ON c.scvid = U.scvid
LEFT JOIN cteSponsor S ON c.ScvId = S.ScvId
LEFT JOIN cteLeinster L on c.ScvId = L.ScvId
LEFT JOIN vwAggTransaction T ON c.ScvId = T.ScvId
group by c.[ScvId]
Title,
FirstName,
LastName,
EmailAddress,
DateOfBirth,
Address1,
City,
Telephone,
Gender,
URC_OptIn,
Partner_OptIn,
Leinster_OptIn,
order by c.scvid
How can I change query to make it run quicker?
Update
I became brave and re-wrote query. I was hesitating as my friend wrote the ctes and I thought that they are necessary.
This version works well and fast. Thank you everyone. I really appreciate your input!
SELECT (c.[ScvId])
,Title
,FirstName
,LastName
,EmailAddress
,DateOfBirth
,Address1
,City
,Telephone
,Gender
,MAX(CASE WHEN who = 'urc' AND OptIn = '1' THEN 1 ELSE 0 END) AS URC_OptIn
,MAX(CASE WHEN who = 'sponsor/3rd party' AND OptIn = '1' THEN 1 ELSE 0 END) AS Partner_OptIn
,MAX(CASE WHEN who = 'leinster rugby' AND OptIn = '1' THEN 1 ELSE 0 END) AS Leinster_OptIn
,MAX(CASE WHEN who = 'connacht rugby' AND OptIn = '1' THEN 1 ELSE 0 END) AS Connacht_OptIn
,MAX(CASE WHEN c.ScvId = T.ScvId AND ProductId = '2019' THEN 1 ELSE 0 END) AS FinalTicketPurchaser_2019
,MAX(CASE WHEN c.ScvId = T.ScvId AND ProductId = '2018' THEN 1 ELSE 0 END) AS FinalTicketPurchaser_2018
FROM vwCustomer c
LEFT JOIN OptIn o ON c.scvid = o.scvid
LEFT JOIN vwAggTransaction T ON c.ScvId = T.ScvId
group by c.[ScvId]
,Title
,FirstName
,LastName
,EmailAddress
,DateOfBirth
,Address1
,City
,Telephone
,Gender
order by c.scvid
I'm taking a stab at it without more information. I converted the CTE into OUTER APPLY. You might need to tweak it a bit for the cases when OptIn=0. Give it a try and see if the performance is any better.
SELECT distinct c.[ScvId]
,Title
,FirstName
,LastName
,EmailAddress
,DateOfBirth
,Address1
,City
,Telephone
,Gender
,URC_OptIn
,Partner_OptIn
,Leinster_OptIn
,MAX(CASE WHEN c.ScvId = T.ScvId AND ProductId = '2019' THEN 1 ELSE 0 END) AS FinalTicketPurchaser_2019
,MAX(CASE WHEN c.ScvId = T.ScvId AND ProductId = '2018' THEN 1 ELSE 0 END) AS FinalTicketPurchaser_2018
FROM scv.vwCustomer c
OUTER APPLY (
SELECT TOP 1 OptIn AS URC_OptIn
FROM scv.OptIn oiu
WHERE oiu.scvid = c.Scvid AND oiu.OptIn = '1' AND oiu.who = 'urc'
) AS U
OUTER APPLY (
SELECT TOP 1 OptIn AS Partner_OptIn
FROM scv.OptIn ois
WHERE ois.scvid = c.Scvid AND ois.OptIn = '1' AND ois.who = 'sponsor/3rd party'
) AS S
OUTER APPLY (
SELECT TOP 1 OptIn AS Leinster_OptIn
FROM scv.OptIn oil
WHERE oil.scvid = c.Scvid AND oil.OptIn = '1' AND oil.who = 'leinster rugby'
) AS L
LEFT JOIN vwAggTransaction T ON c.ScvId = T.ScvId
GROUP BY c.[ScvId]
Title,
FirstName,
LastName,
EmailAddress,
DateOfBirth,
Address1,
City,
Telephone,
Gender,
URC_OptIn,
Partner_OptIn,
Leinster_OptIn,
ORDER BY c.scvid

Better performance for running this query

I want to improve the performance for running the following SQL.
Apparently its taking up 3.28 minutes to run 784 for the following query,
is there a better practice, or better solution to improve the performance of the code? Thanks so much
I've tried with Sum, Count, pivot and looks like Count is faster
with Accounts as
(select ID,displayName AccountName from u3_system.dbo.account with(nolock)
where
ID = '0439b9d9-f2c9-43dc-aa2d-08cdea94db21'
or ID = 'f815d2dd-e118-4930-a67d-08cf28b410e2'
or ID = 'f606fcab-dcbd-4d02-8161-08d635cd8971'
or ID = '7d8f44d4-0f17-41f1-87e2-08cf28b4343b'),
Campaign as
(select C.ID, Accounts.AccountName,C.displayName [Mailout Folder] from Accounts
left join u3_mail.dbo.Campaign C with(nolock)
on C.listID = Accounts.ID),
mo as
(select
campaign.AccountName
,campaign.[Mailout Folder]
,mo.ID [MailOutID]
,mo.displayName [Mailout Name]
,[date] [Send Date]
,Details.value('(//content)[1]/subject[1]', 'varchar(200)') AS [Subject Line]
from campaign
inner join [u3_mail].[dbo].[mailout] mo WITH(NOLOCK)
on mo.campaignID = campaign.ID),
ML as
(select mailoutID,
count(mailoutId) [Total Messages],
count(case when status = 'Delivered' then 1 else null end) Delivered,
count(case when status <> 'Delivered' then 1 else null end) Undelivered,
count(case when ReadDate is not null then 1 else null end) [Read],
count(case when HasClicked = '1' then 1 else null end) [Unique Clicks],
count(case when BounceDate is not null then 1 else null end) [Bounced],
count(case when OptOutDate is not null then 1 else null end) [Opted Out]
from
[u3_data].[data].[MailLog_0439b9d9f2c943dcaa2d08cdea94db21] ML with(nolock)
group by MailoutID
union
select mailoutID,
count(mailoutId) [Total Messages],
count(case when status = 'Delivered' then 1 else null end) Delivered,
count(case when status <> 'Delivered' then 1 else null end) Undelivered,
count(case when ReadDate is not null then 1 else null end) [Read],
count(case when HasClicked = '1' then 1 else null end) [Unique Clicks],
count(case when BounceDate is not null then 1 else null end) [Bounced],
count(case when OptOutDate is not null then 1 else null end) [Opted Out]
from
[u3_data].[data].[MailLog_f815d2dde1184930a67d08cf28b410e2] ML with(nolock)
group by MailoutID
union
select mailoutID,
count(mailoutId) [Total Messages],
count(case when status = 'Delivered' then 1 else null end) Delivered,
count(case when status <> 'Delivered' then 1 else null end) Undelivered,
count(case when ReadDate is not null then 1 else null end) [Read],
count(case when HasClicked = '1' then 1 else null end) [Unique Clicks],
count(case when BounceDate is not null then 1 else null end) [Bounced],
count(case when OptOutDate is not null then 1 else null end) [Opted Out]
from
[u3_data].[data].[MailLog_f606fcabdcbd4d02816108d635cd8971] ML with(nolock)
group by MailoutID
union
select mailoutID,
count(mailoutId) [Total Messages],
count(case when status = 'Delivered' then 1 else null end) Delivered,
count(case when status <> 'Delivered' then 1 else null end) Undelivered,
count(case when ReadDate is not null then 1 else null end) [Read],
count(case when HasClicked = '1' then 1 else null end) [Unique Clicks],
count(case when BounceDate is not null then 1 else null end) [Bounced],
count(case when OptOutDate is not null then 1 else null end) [Opted Out]
from
[u3_data].[data].[MailLog_7d8f44d40f1741f187e208cf28b4343b] ML with(nolock)
group by MailoutID
),
ME as
(select MailoutID,
count(case when [Event] = 'LinkClicked' then 1 else null end) [Total Clicks],
count(case when [Event] = 'AbuseReport' then 1 else null end) [Mark as Spam]
from
[u3_data].[data].[MailEvent_0439b9d9f2c943dcaa2d08cdea94db21] ME with(nolock)
inner join [u3_data].[data].[MailLog_0439b9d9f2c943dcaa2d08cdea94db21] ML with(nolock)
on ML.ID = ME.messageID
where [Event] in ('LinkClicked','AbuseReport')
group by MailoutID
union
select MailoutID,
count(case when [Event] = 'LinkClicked' then 1 else null end) [Total Clicks],
count(case when [Event] = 'AbuseReport' then 1 else null end) [Mark as Spam]
from
[u3_data].[data].[MailEvent_f815d2dde1184930a67d08cf28b410e2] ME with(nolock)
inner join [u3_data].[data].[MailLog_f815d2dde1184930a67d08cf28b410e2] ML with(nolock)
on ML.ID = ME.messageID
where [Event] in ('LinkClicked','AbuseReport')
group by MailoutID
union
select MailoutID,
count(case when [Event] = 'LinkClicked' then 1 else null end) [Total Clicks],
count(case when [Event] = 'AbuseReport' then 1 else null end) [Mark as Spam]
from
[u3_data].[data].[MailEvent_f606fcabdcbd4d02816108d635cd8971] ME with(nolock)
inner join [u3_data].[data].[MailLog_f606fcabdcbd4d02816108d635cd8971] ML with(nolock)
on ML.ID = ME.messageID
where [Event] in ('LinkClicked','AbuseReport')
group by MailoutID
union
select MailoutID,
count(case when [Event] = 'LinkClicked' then 1 else null end) [Total Clicks],
count(case when [Event] = 'AbuseReport' then 1 else null end) [Mark as Spam]
from
[u3_data].[data].[MailEvent_7d8f44d40f1741f187e208cf28b4343b] ME with(nolock)
inner join [u3_data].[data].[MailLog_7d8f44d40f1741f187e208cf28b4343b] ML with(nolock)
on ML.ID = ME.messageID
where [Event] in ('LinkClicked','AbuseReport')
group by MailoutID)
select
mo.AccountName [Account Name]
,mo.[Mailout Folder]
,mo.[Mailout Name]
,mo.[Send Date]
,mo.[Subject line]
,ml.[Total Messages]
,ml.Delivered
,ml.Undelivered
,ml.[Read]
,ml.Delivered - ml.[Read] [Unread]
,ml.[Unique Clicks]
,me.[Total Clicks]
,ml.[Bounced]
,ml.[Opted Out]
,me.[Mark as Spam]
from mo
left join ml
on ml.mailoutID = mo.mailoutID
left join me
on me.mailoutID = ml.mailoutID

Need to add a subquery in a CASE expression that is part of an aggregate function

I need to add the number of records in which the status is set to 'reopened'. But the 'reopened' status has several IDs.
This is the subquery that will Id the 'reopen' statuses:
SELECT (CASE WHEN s.sr_status_recid = 1 THEN 1 ELSE 0 END) AS Reopened
from v_rpt_service s
where vsrv.sr_status_recid in
(select distinct SR_Status_RecID from SR_Status where [Description] like '%Re-opened%'))
This is the main query that the above query needs to be a part:
SELECT DATEPART(WK, vsrv.date_entered) as WkNumber,
COUNT(vsrv.TicketNbr) AS OpenedIssues, --total ticket count
SUM(CASE WHEN vsrv.Closed_Flag = 1 THEN 1 ELSE 0 END) AS ClosedIssues, --sum of tickets with closed_flag = 1
(SELECT SUM(CASE WHEN s.sr_status_recid = 1 THEN 1 ELSE 0 END)
from v_rpt_service s
where vsrv.sr_status_recid in
(select distinct SR_Status_RecID from SR_Status where [Description] like '%Re-opened%')) AS ReopenedIssues,
SUM(CASE WHEN vsrvy.Surveys_Completed = 1 THEN 1 ELSE 0 END) AS SurveysCompletedWithConnectWise, -- Surveys_Completed flag in view is 1
SUM(CASE WHEN Source = 'Portal' THEN 1 ELSE 0 END) AS IssueLoggedPortal,
SUM(CASE WHEN Source = 'Email Connector' THEN 1 ELSE 0 END) AS IssueLoggedEmai
FROM v_rpt_service vsrv LEFT OUTER JOIN v_rpt_SurveysByTicket vsrvy ON vsrv.TicketNbr = Vsrvy.SR_Service_RecID
WHERE vsrv.company_name <> 'XYZ Test Company' AND vsrv.date_entered BETWEEN '01/01/2016' AND '10/07/2016'
GROUP BY DATEPART(WK, vsrv.date_entered)
ORDER BY WkNumber
How can I have a subquery that uses a CASE statement and the CASE statement is aggregated?
You can use CROSS APPLY
SELECT DATEPART(WK, vsrv.date_entered) as WkNumber,
COUNT(vsrv.TicketNbr) AS OpenedIssues, --total ticket count
SUM(CASE WHEN vsrv.Closed_Flag = 1 THEN 1 ELSE 0 END) AS ClosedIssues, --sum of tickets with closed_flag = 1
SUM(CountReopen.YesNo) AS NumberOfReopen,
SUM(CASE WHEN vsrvy.Surveys_Completed = 1 THEN 1 ELSE 0 END) AS SurveysCompletedWithConnectWise, -- Surveys_Completed flag in view is 1
SUM(CASE WHEN Source = 'Portal' THEN 1 ELSE 0 END) AS IssueLoggedPortal,
SUM(CASE WHEN Source = 'Email Connector' THEN 1 ELSE 0 END) AS IssueLoggedEmail
FROM v_rpt_service vsrv
LEFT OUTER JOIN v_rpt_SurveysByTicket vsrvy
ON vsrv.TicketNbr = Vsrvy.SR_Service_RecID
CROSS APPLY (
SELECT IIF(COUNT(*) > 0,1,0) YesNo
FROM SR_Status
where [Description] like '%Re-opened%'
AND SR_Status_ID = vsrv.sr_status_recid
) CountReopen(YesNo)
WHERE vsrv.company_name <> 'XYZ Test Company'
AND vsrv.date_entered BETWEEN '01/01/2016' AND '10/07/2016'
GROUP BY DATEPART(WK, vsrv.date_entered)
ORDER BY WkNumber

SQL Server: Left outer join on whether ID exists

The first three items from table ProviderValueCard add their respective amount if = 1. I'm also trying to add 50 to my TotalScore if the ProviderID exists in table SubscriptionsTV. GroupID is also from SubscriptionsTV in which the condition needs to be met. I beleive I need to have a left outer join in the 2nd query on ProviderID columns from both tables.
DECLARE #ProviderID int = '1717';
WITH cte as(
SELECT TOP 1 ProviderID, Time_Stamp,
SUM(CASE WHEN [AdditionalReports] = '1' THEN 5 ELSE 0 END) as AdditionalReports,
SUM(CASE WHEN [UniqueReportRequests] = '1' THEN 15 ELSE 0 END) as UniqueReportsRequests,
SUM(CASE WHEN [SurveyCompleted] = '1' THEN 30 ELSE 0 END) as SurveyCompleted
--IF #ProviderID EXISTS SUM(THEN 50 ELSE 0 END)
FROM ProviderValueCard
WHERE ProviderID = #ProviderID
GROUP BY Time_Stamp, ProviderID
ORDER BY Time_Stamp DESC
)
SELECT ProviderID, Time_Stamp, (AdditionalReports + UniqueReportsRequests + SurveyCompleted) AS TotalScore
FROM cte
--WHERE GroupID = 2
returns
ProviderID Time_Stamp TotalScore
----------- ----------------------- -----------
1717 2014-08-28 13:03:30.593 45
ProviderValueCard table
ProviderID AdditionalReports UniqueReportRequests SurveyCompleted Time_Stamp
----------- ----------------- -------------------- --------------- -----------------------
1717 0 1 1 2014-08-28 13:03:30.593
SubscriptionsTV table
ProviderID GroupID
----------- -----------
1717 2
My final result is this:
DECLARE #ProviderID int = '1717';
WITH cte as(
SELECT TOP 1 a.ProviderID, Time_Stamp,
SUM(CASE WHEN [AdditionalReports] = '1' THEN 5 ELSE 0 END) as AdditionalReports,
SUM(CASE WHEN [UniqueReportRequests] = '1' THEN 15 ELSE 0 END) as UniqueReportsRequests,
SUM(CASE WHEN [SurveyCompleted] = '1' THEN 30 ELSE 0 END) as SurveyCompleted,
MAX(CASE WHEN b.ProviderID IS NULL THEN 0 ELSE 50 END) as SubscriptionExists
FROM ProviderValueCard a
LEFT JOIN SubscriptionsTV b
ON a.ProviderID = b.ProviderID
WHERE a.ProviderID = #ProviderID AND GroupID = 2
GROUP BY Time_Stamp, a.ProviderID, event
ORDER BY event DESC, Time_Stamp DESC
)
SELECT ProviderID, Time_Stamp, (AdditionalReports + UniqueReportsRequests + SurveyCompleted + SubscriptionExists) AS TotalScore
FROM cte
You are correct that this can be accomplished with a LEFT JOIN, and I'd use MAX() with a CASE statement:
DECLARE #ProviderID int = '1717';
WITH Subs AS (SELECT DISTINCT ProviderID
FROM SubscriptionsTV
)
,cte AS (SELECT TOP 1 a.ProviderID, Time_Stamp,
SUM(CASE WHEN [AdditionalReports] = '1' THEN 5 ELSE 0 END) as AdditionalReports,
SUM(CASE WHEN [UniqueReportRequests] = '1' THEN 15 ELSE 0 END) as UniqueReportsRequests,
SUM(CASE WHEN [SurveyCompleted] = '1' THEN 30 ELSE 0 END) as SurveyCompleted,
MAX(CASE WHEN b.ProviderID IS NULL THEN 0 ELSE 50 END) as SubscriptionExists
FROM ProviderValueCard a
LEFT JOIN Subs b
ON a.ProviderID = b.ProviderID
WHERE a.ProviderID = #ProviderID
GROUP BY Time_Stamp, ProviderID
ORDER BY Time_Stamp DESC
)
SELECT ProviderID, Time_Stamp, (AdditionalReports + UniqueReportsRequests + SurveyCompleted + SubscriptionExists) AS TotalScore
FROM cte
Update: Since multiple providerID's can exist, need DISTINCT, used a 2nd cte above, could also use a correlated sub-select inside the CASE statement.
Wasn't paying attention, ORDER BY is fine in a cte when TOP is used.

SQL Joins : in, out, shake it all about

I am performing the follwing sql to return a data where there is a match of both dob and address in tables1 & 2.
select table1.dob
, table1.address
, sum(case when person_status in ('A','B','C') then 1 else 0 end) as 'ABC_count'
, sum(case when person_status in ('D','E') then 1 else 0 end) as 'DE_Count'
, sum(case when person_status in ('F','G') then 1 else 0 end) as 'FG_Count'
from table1
inner join table2
on (table1.dob = table2.dob and table1.address = table2.address)
where table1.dob > #myDate
group by table1.dob, table1.address
order by table1.dob, table1.address
However I now want to return the data from table1 when there is no match in table2 and only that data, I thought simply changing inner join to left outer would perform what I required, it does not.
Thanks!
If there is no match in the join, the field from the second table are NULL, so you have to check for a NULL value in table2. Assuming dob is NOT NULL in table2, this should solve your problem:
select table1.dob
, table1.address
, sum(case when person_status in ('A','B','C') then 1 else 0 end) as 'ABC_count'
, sum(case when person_status in ('D','E') then 1 else 0 end) as 'DE_Count'
, sum(case when person_status in ('F','G') then 1 else 0 end) as 'FG_Count'
from table1
left outer join table2
on (table1.dob = table2.dob and table1.address = table2.address)
where table1.dob > #myDate and table2.dob is null
group by table1.dob, table1.address
order by table1.dob, table1.address
In this case thre's not a join, you should use NOT EXISTS function.
In my opinion LEFT JOIN is much more cleaner and you should go with that if there is no big difference between the performance of LEFT JOIN and NOT EXISTS. #JNK said "EXISTS and NOT EXISTS are ordinarily faster than joins or other operators like IN because they short circuit - the first time they get a hit they move on to the next entry", but my understanding is that NOT EXISTS and NOT IN are usually expensive as sql server has to go through all the records in the lookup table to make sure that the entry in fact does NOT EXIST, so i dont know how the short circuit would work
You could also use the EXCEPT keyword here.
select table1.dob
, table1.address
, sum(case when person_status in ('A','B','C') then 1 else 0 end) as 'ABC_count'
, sum(case when person_status in ('D','E') then 1 else 0 end) as 'DE_Count'
, sum(case when person_status in ('F','G') then 1 else 0 end) as 'FG_Count'
from table1
where table1.dob > #myDate
EXCEPT
select table1.dob
, table1.address
, sum(case when person_status in ('A','B','C') then 1 else 0 end) as 'ABC_count'
, sum(case when person_status in ('D','E') then 1 else 0 end) as 'DE_Count'
, sum(case when person_status in ('F','G') then 1 else 0 end) as 'FG_Count'
from table1
inner join table2
on (table1.dob = table2.dob and table1.address = table2.address)
where table1.dob > #myDate
That would get you all of the records in the first query that are not in the second query.

Resources