滥用数据库视图(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 以获取所有列,如星期六、星期日、星期一