Adding new table to existing query - sql

I have this existing query that works fine:
SELECT data_tool.name as tool,
MIN(data_cst.date_time) "start",
MAX(data_cst.date_time) "end",
data_cst.recipe_id,
data_target.name as target,
data_lot.name as lot,
data_wafer.name as wafer,
data_measparams.name as mp
FROM data_cst
INNER JOIN data_tool ON data_tool.id = data_cst.tool_id
INNER JOIN data_target ON data_target.id = data_cst.target_name_id
INNER JOIN data_lot ON data_lot.id = data_cst.lot_id
INNER JOIN data_wafer ON data_wafer.id = data_cst.wafer_id
INNER JOIN data_measparams ON data_measparams.id = data_cst.meas_params_name_id
WHERE data_target.id IN (130, 539)
AND data_cst.date_time BETWEEN '2010-01-11 00:00:00' AND '2013-01-11 23:59:59'
AND data_cst.tool_id IN (14,16)
GROUP BY wafer_id, data_cst.lot_id, data_file_id, target_name_id
HAVING count(*) < 100
ORDER BY start, tool
Now I need to add something to it. I have another table called
event_message_idx that has columns recipe_id, lot_id, tool_id,
date_time, and message_idx.
I need to find out how many rows in that table have message_idx = 'OM'
and how many have message_idx = 'SEM' joined with the above query on
recipe_id, lot_id, tool_id and has date_time between start and end.
I have not been able to figure out how to do this in one query (which
I'd really perfer to a sub query as these tables are very large and
the subquery performance has been poor in the past on this system).
I've been playing around with a left join like this:
SELECT data_tool.name as tool,
MIN(data_cst.date_time) "start",
MAX(data_cst.date_time) "end",
data_cst.recipe_id,
data_target.name as target,
data_lot.name as lot,
data_wafer.name as wafer,
data_measparams.name as mp,
event_message_idx.message_idx,
COUNT(event_message_idx.message_idx)
FROM data_cst
LEFT JOIN event_message_idx
ON event_message_idx.recipe_id = data_cst.recipe_id
AND event_message_idx.message_idx IN ('OM', 'SEM')
AND event_message_idx.lot_id = data_cst.lot_id
AND event_message_idx.tool_id = data_cst.tool_id
INNER JOIN data_tool ON data_tool.id = data_cst.tool_id
INNER JOIN data_target ON data_target.id = data_cst.target_name_id
INNER JOIN data_lot ON data_lot.id = data_cst.lot_id
INNER JOIN data_wafer ON data_wafer.id = data_cst.wafer_id
INNER JOIN data_measparams ON data_measparams.id = data_cst.meas_params_name_id
WHERE data_target.id IN (130, 539)
AND data_cst.date_time BETWEEN '2010-01-11 00:00:00' AND '2013-01-11 23:59:59'
AND data_cst.tool_id IN (14,16)
GROUP BY wafer_id, data_cst.lot_id, data_file_id, target_name_id,
event_message_idx.message_idx
HAVING count(*) < 100
ORDER BY start, tool
But there are 2 issues here:
I get double the number of rows I want - one for OM and one for SEM
I don't want that - I just want to know how many OM and SEM rows
there are (really I just want to know if there are 0 or more then 0 -
the actual count doesn't matter).
I am not taking the date range into account - I only want to count
rows from event_message_idx that are between start and end and I can't
figure out how to do that.
Is this possible? I'm thinking it's not and I've have to use 2 queries (which will really complicate the app), or a subquery (which I'm also struggling to write).

calculate those in a subquery, eg
SELECT data_tool.name as tool,
MIN(data_cst.date_time) "start",
MAX(data_cst.date_time) "end",
data_cst.recipe_id,
data_target.name as target,
data_lot.name as lot,
data_wafer.name as wafer,
data_measparams.name as mp,
COALESCE(a.totalOM, 0) totalOM,
COALESCE(a.totalSEM, 0) totalSEM
FROM data_cst
INNER JOIN data_tool
ON data_tool.id = data_cst.tool_id
INNER JOIN data_target
ON data_target.id = data_cst.target_name_id
INNER JOIN data_lot
ON data_lot.id = data_cst.lot_id
INNER JOIN data_wafer
ON data_wafer.id = data_cst.wafer_id
INNER JOIN data_measparams
ON data_measparams.id = data_cst.meas_params_name_id
LEFT JOIN
(
SELECT recipe_id, lot_id, tool_id,
SUM(CASE WHEN message_idx = 'OM' THEN 1 ELSE 0 END) totalOM,
SUM(CASE WHEN message_idx = 'SEM' THEN 1 ELSE 0 END) totalSEM
FROM event_message_idx
WHERE date_time BETWEEN '2010-01-11 00:00:00' AND '2013-01-11 23:59:59'
GROUP BY recipe_id, lot_id, tool_id
) a ON data_cst.recipe_id = a.recipe_id AND
data_cst.lot_id = a.lot_id AND
data_cst.tool_id = a.tool_id
WHERE data_target.id IN (130, 539) AND
(data_cst.date_time BETWEEN '2010-01-11 00:00:00' AND '2013-01-11 23:59:59') AND
data_cst.tool_id IN (14,16)
GROUP BY wafer_id, data_cst.lot_id, data_file_id, target_name_id
HAVING COUNT(*) < 100
ORDER BY `start`, tool

Related

Retrieve all rows using Left Join in Sub Query

Using SQL Server 2008 R2 and I am having issue on retrieving rows using left join in sub query having two different date range.
Tables that i used to store values
And so far I used this sql to retrieve the output (Learnt from Stack overflow)
SELECT
TT.TransferRId, RM.ResourceName AS BookName,
COALESCE(Opening,0) AS Opening,
SUM(TT.InwardQty) AS Inward,
SUM(TT.OutwardQty) AS Outward,
COALESCE((Opening + (SUM(TT.InwardQty)) - (SUM(TT.OutwardQty))), 0) AS Closing
FROM
((ResourceMaster RM
LEFT JOIN
TransferTrans TT ON TT.TransferRId = RM.ResourceId)
LEFT JOIN
TransferRegister TR ON TR.TransferRegisterId = TT.TransRegisterId)
LEFT JOIN
(SELECT
TT.TransferRId,
(SUM(TT.InwardQty)- SUM(TT.OutwardQty)) AS Opening
FROM
TransferTrans TT
LEFT JOIN
TransferRegister TR ON TR.TransferRegisterId = TT.TransRegisterId
WHERE
TR.TransferDate < '2018-09-01'
AND TT.Siteid = 2
GROUP BY
TT.TransferRId) AS Stock ON Stock.TransferRId = TT.TransferRId
WHERE
TT.Siteid = 2
AND TR.TransferDate BETWEEN '2018-09-01' AND '2018-09-30'
GROUP BY
TT.TransferRId, RM.ResourceName, Opening
Output for Above Query
Expected Output
Advise further to get the expected output. Thanks in advance.
The Where-condition on TransferDate changes the Left join to an Inner Join, move it to the On:
SELECT
TT.TransferRId, RM.ResourceName AS BookName,
COALESCE(Opening,0) AS Opening,
SUM(TT.InwardQty) AS Inward,
SUM(TT.OutwardQty) AS Outward,
COALESCE((Opening + (SUM(TT.InwardQty)) - (SUM(TT.OutwardQty))), 0) AS Closing
FROM
ResourceMaster RM
LEFT JOIN
TransferTrans TT ON TT.TransferRId = RM.ResourceId
LEFT JOIN
TransferRegister TR
ON TR.TransferRegisterId = TT.TransRegisterId
AND TR.TransferDate BETWEEN '2018-09-01' AND '2018-09-30'
LEFT JOIN
(SELECT
TT.TransferRId,
(SUM(TT.InwardQty)- SUM(TT.OutwardQty)) AS Opening
FROM
TransferTrans TT
LEFT JOIN
TransferRegister TR
ON TR.TransferRegisterId = TT.TransRegisterId
AND TR.TransferDate < '2018-09-01'
WHERE TT.Siteid = 2
GROUP BY
TT.TransferRId) AS Stock ON Stock.TransferRId = TT.TransferRId
WHERE
TT.Siteid = 2
GROUP BY
TT.TransferRId, RM.ResourceName, Opening
There's a rule of thumb which usually fits: Conditions on the Outer table are put in WHERE while conditions on the Inner table are ANDed to the join-condition in ON

SQL Query with counts only returning equivalent counts

I have a query that consists of 1 table and 2 sub queries. The table being a listing of all customers, 1 sub query is a listing all of the quotes given over a period of time for customers and the other sub query is a listing of all of the orders booked for a customer over the same period of time. What I am trying to do is return a result set that is a customer, the number of quotes given, and the number of orders booked over a given period of time. However what I am returning is only a listening of customers over the period of time that have an equivalent quote and order count. I feel like I am missing something obvious within the context of the query but I am unable to figure it out. Any help would be appreciated. Thank you.
Result Set should look like this
Customer-------Quotes-------Orders Placed
aaa----------------4----------------4
bbb----------------9----------------18
ccc----------------18----------------9
select
[Customer2].[Name] as [Customer2_Name],
(count( Quotes.UD03_Key3 )) as [Calculated_CustomerQuotes],
(count( Customer_Bookings.OrderHed_OrderNum )) as [Calculated_CustomerBookings]
from Erp.Customer as Customer2
left join (select
[UD03].[Key3] as [UD03_Key3],
[UD03].[Key4] as [UD03_Key4],
[UD03].[Key1] as [UD03_Key1],
[UD03].[Date02] as [UD03_Date02]
from Ice.UD03 as UD03
inner join Ice.UD02 as UD02 on
UD03.Company = UD02.Company
And
CAST(CAST(UD03.Number09 AS INT) AS VARCHAR(30)) = UD02.Key1
left outer join Erp.Customer as Customer on
UD03.Company = Customer.Company
And
UD03.Key1 = Customer.Name
left outer join Erp.SalesTer as SalesTer on
Customer.Company = SalesTer.Company
And
Customer.TerritoryID = SalesTer.TerritoryID
left outer join Erp.CustGrup as CustGrup on
Customer.Company = CustGrup.Company
And
Customer.GroupCode = CustGrup.GroupCode
where (UD03.Key3 <> '0')) as Quotes on
Customer2.Name = Quotes.UD03_Key1
left join (select
[Customer1].[Name] as [Customer1_Name],
[OrderHed].[OrderNum] as [OrderHed_OrderNum],
[OrderDtl].[OrderLine] as [OrderDtl_OrderLine],
[OrderHed].[OrderDate] as [OrderHed_OrderDate]
from Erp.OrderHed as OrderHed
inner join Erp.Customer as Customer1 on
OrderHed.Company = Customer1.Company
And
OrderHed.BTCustNum = Customer1.CustNum
inner join Erp.OrderDtl as OrderDtl on
OrderHed.Company = OrderDtl.Company
And
OrderHed.OrderNum = OrderDtl.OrderNum) as Customer_Bookings on
Customer2.Name = Customer_Bookings.Customer1_Name
where Quotes.UD03_Date02 >= '5/15/2018' and Quotes.UD03_Date02 <= '5/15/2018' and Customer_Bookings.OrderHed_OrderDate >='5/15/2018' and Customer_Bookings.OrderHed_OrderDate <= '5/15/2018'
group by [Customer2].[Name]
You have several problems going on here. The first problem is your code is so poorly formatted it is user hostile to look at. Then you have left joins being logically treated an inner joins because of the where clause. You also have date literal strings in language specific format. This should always be the ANSI format YYYYMMDD. But in your case your two predicates are contradicting each other. You have where UD03_Date02 is simultaneously greater than and less than the same date. Thankfully you have =. But if your column is a datetime you have prevented any rows from being returned again (the first being your where clause). You have this same incorrect date logic and join in the second subquery as well.
Here is what your query might look like with some formatting so you can see what is going on. Please note I fixed the logical join issue. You still have the date problems because I don't know what you are trying to accomplish there.
select
[Customer2].[Name] as [Customer2_Name],
count(Quotes.UD03_Key3) as [Calculated_CustomerQuotes],
count(Customer_Bookings.OrderHed_OrderNum) as [Calculated_CustomerBookings]
from Erp.Customer as Customer2
left join
(
select
[UD03].[Key3] as [UD03_Key3],
[UD03].[Key4] as [UD03_Key4],
[UD03].[Key1] as [UD03_Key1],
[UD03].[Date02] as [UD03_Date02]
from Ice.UD03 as UD03
inner join Ice.UD02 as UD02 on UD03.Company = UD02.Company
And CAST(CAST(UD03.Number09 AS INT) AS VARCHAR(30)) = UD02.Key1
left outer join Erp.Customer as Customer on UD03.Company = Customer.Company
And UD03.Key1 = Customer.Name
left outer join Erp.SalesTer as SalesTer on Customer.Company = SalesTer.Company
And Customer.TerritoryID = SalesTer.TerritoryID
left outer join Erp.CustGrup as CustGrup on Customer.Company = CustGrup.Company
And Customer.GroupCode = CustGrup.GroupCode
where UD03.Key3 <> '0'
) as Quotes on Customer2.Name = Quotes.UD03_Key1
and Quotes.UD03_Date02 >= '20180515'
and Quotes.UD03_Date02 <= '20180515'
left join
(
select
[Customer1].[Name] as [Customer1_Name],
[OrderHed].[OrderNum] as [OrderHed_OrderNum],
[OrderDtl].[OrderLine] as [OrderDtl_OrderLine],
[OrderHed].[OrderDate] as [OrderHed_OrderDate]
from Erp.OrderHed as OrderHed
inner join Erp.Customer as Customer1 on OrderHed.Company = Customer1.Company
And OrderHed.BTCustNum = Customer1.CustNum
inner join Erp.OrderDtl as OrderDtl on OrderHed.Company = OrderDtl.Company
And OrderHed.OrderNum = OrderDtl.OrderNum
) as Customer_Bookings on Customer2.Name = Customer_Bookings.Customer1_Name
and Customer_Bookings.OrderHed_OrderDate >= '20180515'
and Customer_Bookings.OrderHed_OrderDate <= '20180515'
group by [Customer2].[Name]
COUNT() will just give you the number of records. You'd expect this two result columns to be equal. Try structuring it like this:
SUM(CASE WHEN Quote.UD03_Key1 IS NOT NULL THEN 1 ELSE 0 END) AS QuoteCount,
SUM(CASE WHEN Customer_Bookings.Customer1_Name IS NOT NULL THEN 1 ELSE 0 END) AS custBookingCount

Reduce Runtime of T-SQL Query

-- WITH POD was causing the issue, removing this code reduced 2 year pull to 3 mins.
Will post new question to figure out best way to include POD data.
--Edit for clarity, I am a read only user to these tables.
I wrote the below query, but it takes a very long time to execute (20min).
It is currently limited to 1 month, but user wants at least 1 year preferably 2. I assume this would scale time to hours.
Can anyone take a look at let me know if there is a BKM I am not using to improve performance?
Or if there is a better method for a report of this size? At 2 years, it would return ~100K rows from 17 tables.
WITH
POD AS
(
SELECT SHIPMENTS.Delivery
,SHIPMENTS.Shipment_Number
,PROOF_OF_DELIVERY.Shipping_Carrier
,PROOF_OF_DELIVERY.Tracking_Number
,PROOF_OF_DELIVERY.Ship_Method
,PROOF_OF_DELIVERY.POD_Signature
,PROOF_OF_DELIVERY.POD_Date
,PROOF_OF_DELIVERY.POD_Time
FROM
SHIPMENTS
LEFT JOIN PROOF_OF_DELIVERY
ON SHIPMENTS.Shipment_Number = PROOF_OF_DELIVERY.Delivery_Or_Shipment
WHERE Load_Date IN
(
SELECT MAX(Load_Date)
FROM PROOF_OF_DELIVERY
GROUP BY Delivery_Or_Shipment
)
)
SELECT DISTINCT GI.GOODS_ISSUE_DOCUMENT_ID
,GI.SALES_ORDER_ID
,GI.SALES_ORDER_LINE_ID
,GI.SALES_ORDER_TYPE_CODE
,GI.DELIVERY_HEADER_ID
,GI.DELIVERY_ITEM_ID
,FD.FISCAL_MONTH_CODE
,GI.MATERIAL_NUMBER
,GI.SHIPPED_QTY
,SO.ORDERER_NAME
,SO.CREATED_BY
,SO.CONTACT_PERSON
,GI.SOLD_TO_CUSTOMER_ID
,GI.SHIP_TO_CUSTOMER_ID
,GI.ORIGINAL_COMMIT_DATE
,GI.SHIP_FROM_PLANT_ID
,GI.ACTUAL_PGI_DATE
,GI.CUSTOMER_PO_NUMBER
,GI.SHIPPED_PRICE
,(GI.SHIPPED_PRICE * GI.SHIPPED_QTY) AS EXT_SHIPPED_PRICE
,GI.SALES_ORGANIZATION_CODE
,GI.DELIVERY_NOTE_PRIORITY_CODE
,FD.FISCAL_WEEK_CODE
,DV.DIVISION_CODE
,DN.Delivery_Item_Creation_Date
,SOLD.CUSTOMER_SHORT_NAME AS SOLD_TO_CUSTOMER_SHORT_NAME
,SHIP.CUSTOMER_SHORT_NAME AS SHIP_TO_CUSTOMER_SHORT_NAME
,SHIP.Customer_Site_Name
,SHIP.REGION_NAME
,MATD.MATERIAL_DESCRIPTION
,MATD.STANDARD_COST
,(MATD.STANDARD_COST * GI.SHIPPED_QTY) AS EXT_STANDARD_COST
,MATD.GLOBAL_EVENT
,PLT.LEAD_TIME_FOR_ORIGINAL_COMMIT
,OPRM.BASE_PART_CODE
,MATD.PRODUCT_INSP_MEMO
,MATD.MATERIAL_PRICING_GROUP_CODE
,MATD.MATERIAL_STATUS AS MMPP
,PIM.PIM_PBG_GROUPING
,SOL.SHIPPING_CONDITION
,SVO.SERVICE_ORDER_NUM
,SO.CREATION_TIME AS SO_CREATION_TIME
,SOL.CREATED_TIME AS SO_LINE_CREATED_TIME
,SOL.SHIPPING_POINT
,SDT.SALES_DOCUMENT_TYPE_CODE AS SVO_DOCUMENT_TYPE_CODE
,EQU.EQUIPMENT_NUM
,EQU.SERIAL_NUMBER
,EQU.CUSTOMERTOOLID
,POD.Shipment_Number
,POD.Shipping_Carrier
,POD.Tracking_Number
,POD.Ship_Method
,POD.POD_Signature
,POD.POD_Date
,POD.POD_Time
,DATEDIFF(dd,SO.CREATION_TIME,GI.ACTUAL_PGI_DATE) AS Cycle_Time_to_PGI_Days
,DATEDIFF(hh,SO.CREATION_TIME,GI.ACTUAL_PGI_DATE) AS Cycle_Time_to_PGI_Hours
FROM GOODS_ISSUE AS GI
INNER JOIN dbo.Delivery_Notes AS DN
ON GI.DELIVERY_HEADER_ID = DN.DELIVERY_HEADER_CODE AND GI.DELIVERY_ITEM_ID = DN.DELIVERY_ITEM_CODE
INNER JOIN dbo.Customer_View AS SOLD
ON GI.SOLD_TO_CUSTOMER_ID = SOLD.CUSTOMER_CODE
INNER JOIN dbo.Customer_View AS SHIP
ON GI.SOLD_TO_CUSTOMER_ID = SHIP.CUSTOMER_CODE
INNER JOIN dbo.MATERIAL_DETAILS AS MATD
ON GI.MATERIAL_NUMBER = MATD.MATERIAL_NUMBER
INNER JOIN dbo.OPR_MATERIAL_DIM AS OPRM
ON OPRM.MATERIAL_NUMBER = GI.MATERIAL_NUMBER
LEFT JOIN dbo.SM_DATE_DIM AS FD
ON CAST(FD.CALENDAR_DAY AS DATE) = CAST(GI.ACTUAL_PGI_DATE AS DATE)
LEFT JOIN dbo.DIM_PUBLISHED_LEAD_TIME_COMMIT AS PLT
ON PLT.MATERIAL_NUMBER = OPRM.BASE_PART_CODE
LEFT JOIN dbo.PRODUCT_INSP_MEMO_DIM AS PIM
ON PIM.PRODUCT_INSP_MEMO = MATD.PRODUCT_INSP_MEMO
INNER JOIN dbo.SM_SALES_ORDER_LINE_FACT AS SOL
ON SOL.SALES_ORDER_CODE = GI.SALES_ORDER_ID AND SOL.SALES_ORDER_LINE_CODE = GI.SALES_ORDER_LINE_ID
INNER JOIN dbo.SM_SALES_ORDER_FACT AS SO
ON SO.SALES_ORDER_CODE = GI.SALES_ORDER_ID
INNER JOIN dbo.SM_DIVISION_DIM AS DV
ON SO.DIVISION_SID = DV.DIVISION_SID
LEFT JOIN dbo.SERVICE_ORDER_FACT AS SVO
ON SVO.SERVICE_ORDER_NUM = SO.SERVICE_ORDER_NUMBER
LEFT JOIN dbo.SM_SALES_DOCUMENT_TYPE_DIM AS SDT
ON SDT.SALES_DOCUMENT_TYPE_SID = SVO.SALES_DOCUMENT_TYPE_SID
LEFT JOIN dbo.SM_EQUIPMENT_DIM AS EQU
ON EQU.EQUIPMENT_SID = SVO.EQUIPMENT_SID
LEFT JOIN POD
ON POD.Delivery = GI.DELIVERY_HEADER_ID
WHERE GI.ACTUAL_PGI_DATE > GETDATE()-32
AND SOLD_TO_CUSTOMER_ID IN (0010000252,0010000898,0010001121,0010001409,0010001842,0010001852,0010001879,0010001977,0010001978,0010002021,0010002202,0010002227,0010002982,0010003118,0010003176,0010003294,0010005492,0010006904,0010007048,0010007080,0010010381,0010010572,0010010905,0010011999,0010012014,0010012048,0010012571,0010013124,0010013711,0010013713,0010013824,0010014180,0010014188,0010014333,0010015059,0010015313,0010015414,0010015541,0010015544,0010015550)
A CTE is just syntax
I suspect that CTE is evaluated many times
Materialze the CTE to #temp with indexe(s) so it is run once
This cast will hurt it
Make those columns true dates and index them
ON CAST(FD.CALENDAR_DAY AS DATE) = CAST(GI.ACTUAL_PGI_DATE AS DATE)
That where negates the left so you can just do a join
Also that MAX(Load_Date) could match on another shipment
SELECT SHIPMENTS.Delivery
,SHIPMENTS.Shipment_Number
,PROOF_OF_DELIVERY.Shipping_Carrier
,PROOF_OF_DELIVERY.Tracking_Number
,PROOF_OF_DELIVERY.Ship_Method
,PROOF_OF_DELIVERY.POD_Signature
,PROOF_OF_DELIVERY.POD_Date
,PROOF_OF_DELIVERY.POD_Time
FROM SHIPMENTS
JOIN PROOF_OF_DELIVERY
ON SHIPMENTS.Shipment_Number = PROOF_OF_DELIVERY.Delivery_Or_Shipment
WHERE PROOF_OF_DELIVERY.Load_Date IN
(
SELECT MAX(Load_Date)
FROM PROOF_OF_DELIVERY
GROUP BY Delivery_Or_Shipment
)
Pull this up into the join
INNER JOIN dbo.Customer_View AS SOLD
ON GI.SOLD_TO_CUSTOMER_ID = SOLD.CUSTOMER_CODE
AND GI.SOLD_TO_CUSTOMER_ID IN (0010000252,0010000898,0010001121,0010001409,0010001842,0010001852,0010001879,0010001977,0010001978,0010002021,0010002202,0010002227,0010002982,0010003118,0010003176,0010003294,0010005492,0010006904,0010007048,0010007080,0010010381,0010010572,0010010905,0010011999,0010012014,0010012048,0010012571,0010013124,0010013711,0010013713,0010013824,0010014180,0010014188,0010014333,0010015059,0010015313,0010015414,0010015541,0010015544,0010015550)

How can i do a conditional where clause in SQL, for missed back ups?

I have a pretty standard query for a back up aging report. What I want / need to do is have it report on missed back ups. I will need to see the last full database back up older than 2 days. I will also need to see any differential back ups older than the last day and any log back ups older than 30 mins. I'm not sure how to do the conditional where clause.
here's my basic query
SELECT
A.[Server],
A.database_name,
A.last_db_backup_date,
B.backup_type,
B.backup_start_date,
B.expiration_date,
B.backup_size,
B.logical_device_name,
B.physical_device_name,
B.backupset_name,
B.description
FROM
(
SELECT
CONVERT(CHAR(100), SERVERPROPERTY('Servername')) AS Server,
msdb.dbo.backupset.database_name,
MAX(msdb.dbo.backupset.backup_finish_date) AS last_db_backup_date
FROM msdb.dbo.backupmediafamily
INNER JOIN msdb.dbo.backupset ON msdb.dbo.backupmediafamily.media_set_id = msdb.dbo.backupset.media_set_id
GROUP BY
msdb.dbo.backupset.database_name
) AS A
LEFT JOIN
(
SELECT
CONVERT(CHAR(100), SERVERPROPERTY('Servername')) AS Server,
msdb.dbo.backupset.database_name,
msdb.dbo.backupset.backup_start_date,
msdb.dbo.backupset.backup_finish_date,
msdb.dbo.backupset.expiration_date,
msdb.dbo.backupset.backup_size,
msdb.dbo.backupmediafamily.logical_device_name,
msdb.dbo.backupmediafamily.physical_device_name,
msdb.dbo.backupset.name AS backupset_name,
msdb.dbo.backupset.description,
CASE msdb..backupset.type
WHEN 'D' THEN 'Full Database'
WHEN 'L' THEN 'Log'
WHEN 'I' THEN 'Differential'
WHEN 'F' THEN 'File Level'
WHEN 'G' THEN 'File Level Differential'
WHEN 'P' THEN 'Partial'
WHEN 'Q' THEN 'Differential partial'
END AS backup_type
FROM msdb.dbo.backupmediafamily
INNER JOIN msdb.dbo.backupset ON msdb.dbo.backupmediafamily.media_set_id = msdb.dbo.backupset.media_set_id
) AS B
ON A.[server] = B.[server] AND A.[database_name] = B.[database_name] AND A.[last_db_backup_date] = B.[backup_finish_date]
ORDER BY
A.database_name
Use a CASE statement. I'll paste an example from my own work:
SELECT
cplnt.complainant_type AS complainant_type,
cpt.date_received AS complaint_received,
CASE WHEN cpt.date_closed IS NULL
THEN (CURRENT_DATE - cpt.date_received)
ELSE (cpt.date_closed - cpt.date_received)
END AS complaint_age,
cpt.id AS complaint_id,
cs.date_case_received AS case_received,
cs.case_status AS case_stage,
stg.stage AS complaint_stage,
tm.name AS team,
trg.date_completed AS triage_date,
trg.method AS triage_method,
cpt.date_closed AS resolution_date,
cpt.status AS closure_type,
cpt.resolution_type AS resolution_type,
cpt.estimated_time_spent AS CLO_time_investment
FROM
complaints_complaint AS cpt
INNER JOIN
complaints_complainant AS cplnt
ON
cpt.complainant_id = cplnt.id
LEFT OUTER JOIN
complaints_case AS cs
ON
cpt.case_id = cs.id
INNER JOIN
complaints_stage AS stg
ON
cpt.stage_id = stg.id
INNER JOIN
community_team AS tm
ON
cpt.team_id = tm.id
LEFT OUTER JOIN
schemes_scheme AS sc
ON
cs.scheme_id = sc.id
LEFT OUTER JOIN
(SELECT
t1.*,
MIN(date_completed) OVER(PARTITION BY complaint_id) AS seq
FROM
complaints_triage AS t1) AS trg
ON
trg.complaint_id = cpt.id AND trg.date_completed = trg.seq;

Why is my SQL Count Statement is counting too many times

I have a query that is supposed to count how many times a user has logged into two different versions of our software based on unique session ids. My count in my outer select statement however is counting way too many times. For example I get 31000 sessions for one user which is incorrect. It should be something more like 40. Why is this happening?
SELECT X.FirstName, X.LastName, X.CompanyName, X.AQ8Sessions, AQ360Sessions = COUNT(RRUI.SessionId)
FROM(
SELECT RRUI.UserId, RRUI.FirstName, RRUI.LastName, RRUI.CompanyName, COUNT(distinct RRUI.SessionId) AQ8Sessions
FROM Authentication.dbo.RegReportUserInfo RRUI
INNER JOIN Authentication.dbo.RegReportSessions RRS
ON RRUI.SessionId = RRS.SessionId
INNER JOIN WebCatalog.Published.People P
ON P.PKey = RRUI.UserId
WHERE RRUI.ClientType = 'aq8' AND RRS.ExpiresAt <= '2013-11-24 23:59:59.999'
AND RRS.ExpiresAt >= '2013-11-18 00:00:00.000' AND RRUI.CompanyName NOT LIKE 'AutoQuotes%'
AND P.EMail NOT LIKE '%#aqnet.com'
GROUP BY RRUI.FirstName, RRUI.LastName, RRUI.CompanyName, RRUI.UserId
) X
INNER JOIN Authentication.dbo.RegReportSessions RRS
ON RRS.UserId = X.UserId
AND RRS.ExpiresAt <= '2013-11-24 23:59:59.999'
AND RRS.ExpiresAt >= '2013-11-18 00:00:00.000'
LEFT OUTER JOIN Authentication.dbo.RegReportUserInfo RRUI
ON X.UserId = RRUI.UserId AND RRUI.ClientType = 'aq360'
GROUP BY X.FirstName, X.LastName, X.CompanyName, X.AQ8Sessions
ORDER BY X.AQ8Sessions DESC, COUNT(RRUI.SessionId) DESC
Hard to say for sure without seeing the data but I expect one or both of these will fix it:
COUNT(DISTINCT RRUI.SessionId)
and / or
INNER JOIN Authentication.dbo.RegReportUserInfo
where you had
LEFT OUTER JOIN Authentication.dbo.RegReportUserInfo