滥用数据库视图(SQL服务器)——如何优化
Misused database view (SQL Server) - how to optimize
我需要一些关于如何优化 SQL 查询的建议,因为我不是 SQL 方面的专家。
我的一个客户有一些 SQL 代码 运行 在 SQL 服务器上,他们希望它 运行 更快。以前运行快,现在不行了。
查询每天使用同一个巨大的视图 6 次来提取数据,这是它非常慢的主要原因,运行宁 25 分钟以上。
主要问题似乎是视图被调用了很多次,运行s 之间的差别很小。
是否可以重新编写查询,使其只调用一次视图,然后从中提取一周的数据,是否可以在不使用临时表的情况下完成?
-- 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
是的,这是可能的。
按 dateofsale、receiptid、dateofsale 对所有内容进行分组,并应用日期过滤器,然后 PIVOT 结果(将行(一周中的 7 天)旋转到列)
https://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx
使用@justweekEnding 日期过滤器为按列 dateofsale、received、dateofsale 分组的视图创建 CTE(通用类型表达式)。
然后您可以创建一个查询,使用 CTE 连接其他表并执行 Pivot 以获取所有列,如星期六、星期日、星期一
我需要一些关于如何优化 SQL 查询的建议,因为我不是 SQL 方面的专家。
我的一个客户有一些 SQL 代码 运行 在 SQL 服务器上,他们希望它 运行 更快。以前运行快,现在不行了。
查询每天使用同一个巨大的视图 6 次来提取数据,这是它非常慢的主要原因,运行宁 25 分钟以上。
主要问题似乎是视图被调用了很多次,运行s 之间的差别很小。
是否可以重新编写查询,使其只调用一次视图,然后从中提取一周的数据,是否可以在不使用临时表的情况下完成?
-- 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
是的,这是可能的。
按 dateofsale、receiptid、dateofsale 对所有内容进行分组,并应用日期过滤器,然后 PIVOT 结果(将行(一周中的 7 天)旋转到列)
https://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx
使用@justweekEnding 日期过滤器为按列 dateofsale、received、dateofsale 分组的视图创建 CTE(通用类型表达式)。
然后您可以创建一个查询,使用 CTE 连接其他表并执行 Pivot 以获取所有列,如星期六、星期日、星期一