2017-04-05 196 views
1

我的问题是我创建了一个需要太长时间才能执行的查询。SQL Server查询优化

City | Department | Employee | Attendance Date | Attendance Status 
------------------------------------------------------------------------ 
C1  | Dept 1  | Emp 1  | 2016-01-01  | ABSENT 
C1  | Dept 1  | Emp 2  | 2016-01-01  | LATE 
C1  | Dept 2  | Emp 3  | 2016-01-01  | VACANCY 

所以我想创建一个包含相同的数据,并添加含有员工总数(即在SSRS项目,以确定各状态下的百分比后来成为我)一列的视图。

因此,我创建了一个功能,使部门和日期的简单选择过滤。

,这是使用函数的查询:

SELECT  City, Department, Employee, [Attendence Date], [Attendance Status], [Get Department Employees By Date](Department, [Attendence Date]) AS TOTAL 
FROM   attendenceTable 

这是函数:

CREATE FUNCTION [dbo].[Get Department Employees By Date] 
(
    @deptID int = null, 
    @date datetime = null 
) 
RETURNS nvarchar(max) 
AS 
BEGIN 
    declare @result int = 0; 
    select @result = count(*) from attendenceTable where DEPT_ID = @deptID and ATT_DATE_G = @date; 
    RETURN @result; 

END 

的问题是,查询的时间太长(我的意思是很长的时间)来执行。 任何建议优化?

+0

你在该表中有哪些索引?你通常如何过滤这些数据? –

+2

也请包括功能代码。谢谢 –

+0

数据多久改变一次?这可以运行在高峰夜晚吗?数据库是MS SQL?你有索引吗? – lloyd

回答

3

您的函数是一个标量函数,它对结果集中的每一行运行一次(〜600,000次),并且是一个已知的性能杀手。它可以改写成内嵌表值函数,或者如果没有其他地方所需要的逻辑,一个简单的组数&加入就足够了:

WITH EmployeesPerDeptPerDate 
      AS (SELECT DEPT_ID , 
         ATT_DATE_G , 
         COUNT(DISTINCT Employee) AS EmployeeCount 
       FROM  attendenceTable 
       GROUP BY DEPT_ID , 
         ATT_DATE_G 
      ) 
    SELECT A.City , 
      A.Department , 
      A.Employee , 
      A.[Attendence Date] , 
      A.[Attendance Status] , 
      ISNULL(B.EmployeeCount, 0) AS EmployeeCount 
    FROM attendenceTable AS A 
      LEFT OUTER JOIN EmployeesPerDeptPerDate AS B ON A.DEPT_ID = B.DEPT_ID 
                  AND A.ATT_DATE_G = B.ATT_DATE_G;