I need some advice on how to optimize a SQL query, since I am not an expert in SQL.
A customer of mine has some SQL code that runs on SQL Server, and they want it to run faster. It used to run fast, but now it does not.
The query is using the same huge view 6 times to extract data for each day and it is the primary cause for it to be very slow, running for 25+ minutes.
The main issue seems to be that the view is called so many times with so little difference between the runs.
Is it possible to re-write the query so it only calls the view once and then extract the data for the week from that and can it be done without using temp tables?
-- Imput: @justWeekEnding - the date for the end of week report
-- Input: @customerid - the unique customer ID for whom the report is generated
-- Expected output: Sales report, showing profit margin for the selected customer per shop per day-of-week
--
-- dbo.charting_salesdata: View producing a sales report across all stores per date per customer
-- dbo.stores: Table containing store info
-- dbo.receipts: Table containing all receipts
-- dbo.storecategories: Table containing all store categories
DECLARE @justWeekEnding AS date;
SET @justWeekEnding = CONVERT(date, @weekEnding, 101);
SELECT
Query.StoreName AS [Store Name], Query.POS as [POS Name],
Query.saturday, Query.sunday, Query.monday, Query.tuesday,
Query.wednesday, Query.thursday, Query.friday
FROM
(SELECT
dbo.stores.NAME AS [StoreName],
receipts.POS AS [POS],
(SELECT COUNT(percentage)
FROM dbo.charting_salesdata WITH (nolock)
WHERE dbo.charting_salesdata.receiptid = dbo.receipts.receiptid
AND dateofsale = Dateadd(d, -6, @justWeekEnding)
GROUP BY receiptid, dateofsale) AS saturday,
(SELECT COUNT(percentage)
FROM dbo.charting_salesdata WITH (nolock)
WHERE dbo.charting_salesdata.receiptid = dbo.receipts.receiptid
AND dateofsale = Dateadd(d, -5, @justWeekEnding)
GROUP BY receiptid, dateofsale) AS sunday,
(SELECT COUNT(percentage)
FROM dbo.charting_salesdata WITH (nolock)
WHERE dbo.charting_salesdata.receiptid = dbo.receipts.receiptid
AND dateofsale = Dateadd(d, -4, @justWeekEnding)
GROUP BY receiptid, dateofsale) AS monday,
(SELECT COUNT(percentage)
FROM dbo.charting_salesdata WITH (nolock)
WHERE dbo.charting_salesdata.receiptid = dbo.receipts.receiptid
AND dateofsale = Dateadd(d, -3, @justWeekEnding)
GROUP BY receiptid, dateofsale) AS tuesday,
(SELECT COUNT(percentage)
FROM dbo.charting_salesdata WITH (nolock)
WHERE dbo.charting_salesdata.receiptid = dbo.receipts.receiptid
AND dateofsale = Dateadd(d, -2, @justWeekEnding)
GROUP BY receiptid, dateofsale) AS wednesday,
(SELECT COUNT(percentage)
FROM dbo.charting_salesdata WITH (nolock)
WHERE dbo.charting_salesdata.receiptid = dbo.receipts.receiptid
AND dateofsale = Dateadd(d, -1, @justWeekEnding)
GROUP BY receiptid, dateofsale) AS thursday,
(SELECT COUNT(percentage)
FROM dbo.charting_salesdata WITH (nolock)
WHERE dbo.charting_salesdata.receiptid = dbo.receipts.receiptid
AND dateofsale = @justWeekEnding
GROUP BY receiptid, dateofsale) AS friday,
(SELECT COUNT(percentage)
FROM dbo.charting_salesdata WITH (nolock)
WHERE dbo.charting_salesdata.receiptid = dbo.receipts.receiptid
AND dateofsale BETWEEN Dateadd(d, -6, @justWeekEnding) AND @justWeekEnding) AS TOTAL
FROM
receipts WITH (nolock)
INNER JOIN
dbo.stores WITH (nolock) ON dbo.receipts.storeid = dbo.stores.storeid
INNER JOIN
dbo.storecategories WITH (nolock) ON dbo.stores.storecategoryid = dbo.storecategories.storecategoryid
WHERE
1=1
AND customerid = @customerid
AND dbo.receipts.isdeleted = 0) AS Query
WHERE
Query.TOTAL > 0
ORDER BY
Query.StoreName, Query.TargetName