8 c# sql sql-server stored-procedures
我有以下查询,由于有很多SUM函数调用,我的查询运行速度太慢。我的数据库中有很多记录,我想从今年和去年(过去 30 天、过去 90 天和过去 365 天)中获取每个记录的报告:
SELECT
b.id as [ID]
,d.[Title] as [Title]
,e.Class as [Class]
,Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-1,GETDATE()) THEN a.col1 ELSE 0 END) as [Current - Last 30 Days Col1]
,Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-1,GETDATE()) THEN a.col2 ELSE 0 END) as [Current - Last 30 Days Col2]
,Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-1,GETDATE()) THEN a.col1 ELSE 0 END) as [Current - Last 90 Days Col1]
,Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-1,GETDATE()) THEN a.col2 ELSE 0 END) as [Current - Last 90 Days Col2]
,Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-1,GETDATE()) THEN a.col1 ELSE 0 END) as [Current - Last 365 Days Col1]
,Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-1,GETDATE()) THEN a.col2 ELSE 0 END) as [Current - Last 365 Days Col2]
,Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-13,GETDATE()) and a.DateCol <= DATEADD(MONTH,-12,GETDATE()) THEN a.col1 ELSE 0 END) as [Last year - Last 30 Days Col1]
,Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-13,GETDATE()) and a.DateCol <= DATEADD(MONTH,-12,GETDATE()) THEN a.col2 ELSE 0 END) as [Last year - Last 30 Days Col2]
,Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-5,GETDATE()) and a.DateCol <= DATEADD(QUARTER,-4,GETDATE()) THEN a.col1 ELSE 0 END) as [Last year - Last 90 Days Col1]
,Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-5,GETDATE()) and a.DateCol <= DATEADD(QUARTER,-4,GETDATE()) THEN a.col2 ELSE 0 END) as [Last year - Last 90 Days Col2]
,Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-2,GETDATE()) and a.DateCol <= DATEADD(YEAR,-1,GETDATE()) THEN a.col1 ELSE 0 END) as [Last year - Last 365 Days Col1]
,Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-2,GETDATE()) and a.DateCol <= DATEADD(YEAR,-1,GETDATE()) THEN a.col2 ELSE 0 END) as [Last year - Last 365 Days Col2]
FROM
tb1 a
INNER JOIN
tb2 b on a.id=b.fid and a.col3 = b.col4
INNER JOIN
tb3 c on b.fid = c.col5
INNER JOIN
tb4 d on c.id = d.col6
INNER JOIN
tb5 e on c.col7 = e.id
GROUP BY
b.id, d.Title, e.Class
Run Code Online (Sandbox Code Playgroud)
有谁知道如何改进我的查询以更快地运行?
编辑:我被鼓励将DATEADD函数调用移动到where语句并首先加载前两年然后在列中过滤它们,但我不确定建议的答案是否已执行并且有效,可以在此处找到:https://stackoverflow。 com/a/59944426/12536284
如果您同意上述解决方案,请告诉我如何将其应用到我当前的查询中?
仅供参考,我在 C#、实体框架(DB-First)中使用这个 SP,如下所示:
var result = MyDBEntities.CalculatorSP();
Run Code Online (Sandbox Code Playgroud)
正如已经提到的,在这种情况下,执行计划将非常有用。根据您所展示的内容,您似乎已经从 中提取了 12 列,共 15 列tb1 (a),因此您可以尝试在没有任何连接的情况下运行查询,并仅针对tb1来查看您的查询是否按预期工作。由于我看不出您的 SUM 函数调用有任何问题,我最好的猜测是您的连接有问题,我建议您执行以下操作。例如,您可以先排除最后一个连接,
INNER JOIN tb5 e on c.col7 = e.id以及它的任何相关用法,例如e.Class as [Class]和e.Class在您的组中通过语句。我们不会完全排除它,这只是一个测试,以确保问题是否与此有关,如果您的查询运行得更好并且如预期的那样,您可以尝试使用临时表作为解决方法而不是最后一个连接,像这样:
SELECT *
INTO #Temp
FROM
(
select * from tb5
) As tempTable;
SELECT
b.id as [ID]
,d.[Title] as [Title]
,e.Class as [Class]
-- SUM Functions
FROM
tb1 a
INNER JOIN
tb2 b on a.id=b.fid and a.col3 = b.col4
INNER JOIN
tb3 c on b.fid = c.col5
INNER JOIN
tb4 d on c.id = d.col6
INNER JOIN
#Temp e on c.col7 = e.id
GROUP BY
b.id, d.Title, e.Class
Run Code Online (Sandbox Code Playgroud)
实际上,临时表是临时存在于 SQL Server 上的表。临时表可用于存储多次访问的即时结果集。您可以在此处阅读有关它的更多信息https://www.sqlservertutorial.net/sql-server-basics/sql-server-temporary-tables/ 这里是https://codingsight.com/introduction-to-temporary-tables-in -sql-server/
另外我强烈建议,如果您使用存储过程,将 设置NOCOUNT为ON,它还可以提供显着的性能提升,因为网络流量大大减少:
SET NOCOUNT ON
SELECT *
INTO #Temp
-- The rest of code
Run Code Online (Sandbox Code Playgroud)
基于此:
SET NOCOUNT ON 是一个设置语句,它阻止显示受 T-SQL 查询语句影响的行数的消息。这在存储过程和触发器中使用,以避免显示受影响的行消息。在存储过程中使用 SET NOCOUNT ON 可以显着提高存储过程的性能。
小智 -2
为了提高SQL查询的速度,必须添加索引。对于每个连接的表,您必须添加一个索引。
就像 oracle 的代码示例一样:
CREATE INDEX supplier_idx
ON supplier (supplier_name);
Run Code Online (Sandbox Code Playgroud)