如何优化这个以减少执行时间
how to optimize this one to reduce execution time
Use ReportingDb
select hd.company_name as CompanyName,
COALESCE((select sum(case datepart(dw, hrd.created_datetime)
when 1 then 1 else 0
end) from dbo.HdSurvey_Result_Details hrd where hd.company_id = hrd.company_id and (hrd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10 10:46:19')),0) as Monday,
COALESCE((select sum(case datepart(dw,hrd.created_datetime)
when 2 then 1 else 0
end)from dbo.HdSurvey_Result_Details hrd where hd.company_id = hrd.company_id and (hrd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10 10:46:19')),0) as Tuesday,
COALESCE((select sum(case datepart(dw,hrd.created_datetime)
when 3 then 1 else 0
end)from dbo.HdSurvey_Result_Details hrd where hd.company_id = hrd.company_id and (hrd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10 10:46:19')),0) as Wednesday,
COALESCE((select sum(case datepart(dw,hrd.created_datetime)
when 4 then 1 else 0
end)from dbo.HdSurvey_Result_Details hrd where hd.company_id = hrd.company_id and (hrd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10 10:46:19')),0) as Thursday,
COALESCE((select sum(case datepart(dw,hrd.created_datetime)
when 5 then 1 else 0
end)from dbo.HdSurvey_Result_Details hrd where hd.company_id = hrd.company_id and(hrd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10 10:46:19')),0) as Friday,
COALESCE((select sum(case datepart(dw,hrd.created_datetime)
when 6 then 1 else 0
end)from dbo.HdSurvey_Result_Details hrd where hd.company_id = hrd.company_id and (hrd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10 10:46:19')),0) as Saturday,
COALESCE((select sum(case datepart(dw,hrd.created_datetime)
when 7 then 1 else 0
end)from dbo.HdSurvey_Result_Details hrd where hd.company_id = hrd.company_id and (hrd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10 10:46:19')),0) as Sunday,
COALESCE((select COUNT_BIG(*) from dbo.HdSurvey_Result_Details hrd where hd.company_id = hrd.company_id and(hrd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10 10:46:19')),0) as TotalResults
from HdSurvey_Result_Details as hd
group by hd.company_name,hd.company_id
我认为就时间而言,最初的问题是所有 sub-queries(例如,SELECT SUM(CASE ...
语句)的 amount/approach 可能无法通过查询得到很好的优化优化器。
如果可能,您确实需要尝试简化该方法。这是可能的。理想情况下,您可以将 'SELECT' 组件作为简单的 SUM(CASE ...
语句来执行,而无需完整 sub-queries。这使查询优化器有机会(比如说)决定只读取 table 一次而不是 10 次。
首先,我总是检查分组:每一行应该是什么?在这种情况下,每一行都是一个公司名称。你已经设置好了。
下一步是优化聚合组件。这是您的问题的一个例子(大多数似乎是这样)。为了帮助我,我对其进行了一些不同的格式化。
COALESCE(
(select sum(case datepart(dw, hrd.created_datetime)
when 1 then 1 else 0
end)
from dbo.HdSurvey_Result_Details hrd
where hd.company_id = hrd.company_id and (hrd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10 10:46:19')
),
0) as Monday,
据我所知,这是 a) 按 hrd.created_datetime 过滤,以及 b) 计算周一范围内的行数。
相反,这可以通过将过滤放在 CASE 中来简化 -(消除对完整 sub-query 的需要)例如,
SUM(CASE WHEN datepart(dw, hd.created_datetime) = 1 AND (hd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10 10:46:19') THEN 1 ELSE 0 END) AS Monday
已按公司分组,无需加入it/etc公司。这是由底部的 GROUP BY 处理的。
此外,这是 total_results 值
的一种方法
SUM(CASE WHEN (hd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10 10:46:19') THEN 1 ELSE 0 END) as TotalResults
如果你对所有的聚合值都这样做,我相信你会得到很好的改进。
不过,我们可以更进一步。
您似乎在按相同的日期范围过滤每个 count/sum 值。不要将它包含在 SUM(CASE) 语句中,只需使用 WHERE 子句过滤原始数据,例如
select hd.company_name as [CompanyName],
SUM(CASE WHEN datepart(dw, hd.created_datetime) = 1 THEN 1 ELSE 0 END) AS [Monday],
-- add similar rows for Tuesday to Sunday
-- Total results no longer needs the SUM(CASE) as all rows match
COUNT_BIG(*) as [TotalResults]
from HdSurvey_Result_Details as hd
WHERE (hd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10 10:46:19')
group by hd.company_name, hd.company_id
这意味着不是读取整个 table,然后在整个 table 中计算每个聚合(例如,很多行在您的 SUM 中为 0),您可以改为只读取 table 的一小部分(希望如此),并且只对这个小得多的数据集进行聚合计算。
编辑:拼写错误 - 我在解决方案中留下了一些 hrd table 参考而不是 hd。这些已更改为高清。
更新以下评论 - 包括所有公司名称
要获取所有公司名称,如果不存在则为 0,请将以上内容用作 LEFT JOIN 的一部分(其中左侧 table 是公司名称)。
这是一个示例 - 假设公司存储在 'Company' table 中并具有 CTE。你也可以做一个 sub-query.
; WITH A AS
(select hd.company_Id, -- Note - changed this to company_id rather than company_name
SUM(CASE WHEN datepart(dw, hd.created_datetime) = 1 THEN 1 ELSE 0 END) AS [Monday],
-- add similar rows for Tuesday to Sunday
-- Total results no longer needs the SUM(CASE) as all rows match
COUNT_BIG(*) as [TotalResults]
from HdSurvey_Result_Details as hd
WHERE (hd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10
10:46:19')
group by hd.company_id -- Also changed this to company_id
)
SELECT c.company_name,
COALESCE(A.[Monday],0) AS Monday,
--- other days
COALESCE(A.[TotalResults],0) AS TotalResults
FROM companies AS c
LEFT OUTER JOIN A on c.company_id = A.company_id
Use ReportingDb
select hd.company_name as CompanyName,
COALESCE((select sum(case datepart(dw, hrd.created_datetime)
when 1 then 1 else 0
end) from dbo.HdSurvey_Result_Details hrd where hd.company_id = hrd.company_id and (hrd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10 10:46:19')),0) as Monday,
COALESCE((select sum(case datepart(dw,hrd.created_datetime)
when 2 then 1 else 0
end)from dbo.HdSurvey_Result_Details hrd where hd.company_id = hrd.company_id and (hrd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10 10:46:19')),0) as Tuesday,
COALESCE((select sum(case datepart(dw,hrd.created_datetime)
when 3 then 1 else 0
end)from dbo.HdSurvey_Result_Details hrd where hd.company_id = hrd.company_id and (hrd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10 10:46:19')),0) as Wednesday,
COALESCE((select sum(case datepart(dw,hrd.created_datetime)
when 4 then 1 else 0
end)from dbo.HdSurvey_Result_Details hrd where hd.company_id = hrd.company_id and (hrd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10 10:46:19')),0) as Thursday,
COALESCE((select sum(case datepart(dw,hrd.created_datetime)
when 5 then 1 else 0
end)from dbo.HdSurvey_Result_Details hrd where hd.company_id = hrd.company_id and(hrd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10 10:46:19')),0) as Friday,
COALESCE((select sum(case datepart(dw,hrd.created_datetime)
when 6 then 1 else 0
end)from dbo.HdSurvey_Result_Details hrd where hd.company_id = hrd.company_id and (hrd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10 10:46:19')),0) as Saturday,
COALESCE((select sum(case datepart(dw,hrd.created_datetime)
when 7 then 1 else 0
end)from dbo.HdSurvey_Result_Details hrd where hd.company_id = hrd.company_id and (hrd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10 10:46:19')),0) as Sunday,
COALESCE((select COUNT_BIG(*) from dbo.HdSurvey_Result_Details hrd where hd.company_id = hrd.company_id and(hrd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10 10:46:19')),0) as TotalResults
from HdSurvey_Result_Details as hd
group by hd.company_name,hd.company_id
我认为就时间而言,最初的问题是所有 sub-queries(例如,SELECT SUM(CASE ...
语句)的 amount/approach 可能无法通过查询得到很好的优化优化器。
如果可能,您确实需要尝试简化该方法。这是可能的。理想情况下,您可以将 'SELECT' 组件作为简单的 SUM(CASE ...
语句来执行,而无需完整 sub-queries。这使查询优化器有机会(比如说)决定只读取 table 一次而不是 10 次。
首先,我总是检查分组:每一行应该是什么?在这种情况下,每一行都是一个公司名称。你已经设置好了。
下一步是优化聚合组件。这是您的问题的一个例子(大多数似乎是这样)。为了帮助我,我对其进行了一些不同的格式化。
COALESCE(
(select sum(case datepart(dw, hrd.created_datetime)
when 1 then 1 else 0
end)
from dbo.HdSurvey_Result_Details hrd
where hd.company_id = hrd.company_id and (hrd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10 10:46:19')
),
0) as Monday,
据我所知,这是 a) 按 hrd.created_datetime 过滤,以及 b) 计算周一范围内的行数。
相反,这可以通过将过滤放在 CASE 中来简化 -(消除对完整 sub-query 的需要)例如,
SUM(CASE WHEN datepart(dw, hd.created_datetime) = 1 AND (hd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10 10:46:19') THEN 1 ELSE 0 END) AS Monday
已按公司分组,无需加入it/etc公司。这是由底部的 GROUP BY 处理的。
此外,这是 total_results 值
的一种方法SUM(CASE WHEN (hd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10 10:46:19') THEN 1 ELSE 0 END) as TotalResults
如果你对所有的聚合值都这样做,我相信你会得到很好的改进。
不过,我们可以更进一步。
您似乎在按相同的日期范围过滤每个 count/sum 值。不要将它包含在 SUM(CASE) 语句中,只需使用 WHERE 子句过滤原始数据,例如
select hd.company_name as [CompanyName],
SUM(CASE WHEN datepart(dw, hd.created_datetime) = 1 THEN 1 ELSE 0 END) AS [Monday],
-- add similar rows for Tuesday to Sunday
-- Total results no longer needs the SUM(CASE) as all rows match
COUNT_BIG(*) as [TotalResults]
from HdSurvey_Result_Details as hd
WHERE (hd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10 10:46:19')
group by hd.company_name, hd.company_id
这意味着不是读取整个 table,然后在整个 table 中计算每个聚合(例如,很多行在您的 SUM 中为 0),您可以改为只读取 table 的一小部分(希望如此),并且只对这个小得多的数据集进行聚合计算。
编辑:拼写错误 - 我在解决方案中留下了一些 hrd table 参考而不是 hd。这些已更改为高清。
更新以下评论 - 包括所有公司名称
要获取所有公司名称,如果不存在则为 0,请将以上内容用作 LEFT JOIN 的一部分(其中左侧 table 是公司名称)。
这是一个示例 - 假设公司存储在 'Company' table 中并具有 CTE。你也可以做一个 sub-query.
; WITH A AS
(select hd.company_Id, -- Note - changed this to company_id rather than company_name
SUM(CASE WHEN datepart(dw, hd.created_datetime) = 1 THEN 1 ELSE 0 END) AS [Monday],
-- add similar rows for Tuesday to Sunday
-- Total results no longer needs the SUM(CASE) as all rows match
COUNT_BIG(*) as [TotalResults]
from HdSurvey_Result_Details as hd
WHERE (hd.created_datetime between '2019-10-10 10:46:19' AND '2020-10-10
10:46:19')
group by hd.company_id -- Also changed this to company_id
)
SELECT c.company_name,
COALESCE(A.[Monday],0) AS Monday,
--- other days
COALESCE(A.[TotalResults],0) AS TotalResults
FROM companies AS c
LEFT OUTER JOIN A on c.company_id = A.company_id