2017-04-05 241 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;