2016-11-17 111 views
3

我得到以下錯誤:T-SQL聚合函數子查詢

Cannot perform an aggregate function on an expression containing an aggregate or a subquery. 

有了這個代碼:

SELECT 
    loc.Location 
    ,COUNT(CASE 
     WHEN hr.SAC in (SELECT [SAC] FROM dbo.[Titles] WHERE [title] = 'XYZ') 
      THEN 1 
      ELSE NULL 
     END) AS XYZ_Trainee_Count 
    ,COUNT(CASE 
     WHEN hr.SAC in (SELECT [SAC] FROM dbo.[Titles] WHERE [title] = 'ABC') 
      THEN 1 
      ELSE NULL 
     END) AS ABC_Trainee_Count 

FROM 
    dbo.n_HRODS hr INNER JOIN dbo.Locations loc 
     ON loc.LocationID = hr.LocationID 
    INNER JOIN dbo.EmpData dat 
     ON dat.EmpID = hr.EmpID 

WHERE dat.Trainee = 1 

GROUP BY loc.Location 

DBO [標題]是結合從其他兩個表的兩列的圖。我基本上做這種方式,因爲我之前程序員做了這樣的事情:

,COUNT(CASE 
    WHEN SAC in (lists about 30 items) 
     THEN 1 
     ELSE NULL 
    END) 

顯然,我不想列出該case語句30個項目......當這些項目的任何改變3年後的原因,那麼誰將記得回到這個代碼並更新這些項目?沒有人...

在此先感謝您的幫助。

回答

2

你可以用一些額外的LEFT OUTER JOINstitle表做到這一點:

SELECT 
    loc.Location 
    ,COUNT(CASE WHEN titles1.[SAC] IS NOT NULL THEN 1 ELSE NULL END) AS XYZ_Trainee_Count 
    ,COUNT(CASE WHEN titles2.[SAC] IS NOT NULL THEN 1 ELSE NULL END) AS ABC_Trainee_Count 

FROM 
    dbo.n_HRODS hr INNER JOIN dbo.Locations loc 
     ON loc.LocationID = hr.LocationID 
    INNER JOIN dbo.EmpData dat 
     ON dat.EmpID = hr.EmpID 
    LEFT OUTER JOIN dbo.[Titles] titles1 
     ON titles1.[title]='XYZ' AND 
      hr.SAC = titles1.[SAC] 
    LEFT OUTER JOIN dbo.[Titles] titles2 
     ON titles2.[title]='ABC' AND 
      hr.sac = titles2.[SAC]  
WHERE dat.Trainee = 1  
GROUP BY loc.Location 

或者,如果你真的嫁給你的SELECT語句中的子查詢,因爲實際的查詢是一個很大的噩夢和想與加入胡鬧的是足以讓你昏,然後你可以從這個查詢中刪除聚集和聚合之前,這一切推到一個子查詢:

SELECT location, count(XYZ_Trainee) AS XYZ_Trainee_Count, count(ABC_Trainee) as ABC_Trainee 
FROM 
(
    SELECT 
     loc.Location 
     ,CASE 
      WHEN hr.SAC in (SELECT [SAC] FROM dbo.[Titles] WHERE [title] = 'XYZ') 
       THEN 1 
       ELSE NULL 
      END AS XYZ_Trainee 
     ,CASE 
      WHEN hr.SAC in (SELECT [SAC] FROM dbo.[Titles] WHERE [title] = 'ABC') 
       THEN 1 
       ELSE NULL 
      END AS ABC_Trainee 

    FROM 
     dbo.n_HRODS hr INNER JOIN dbo.Locations loc 
      ON loc.LocationID = hr.LocationID 
     INNER JOIN dbo.EmpData dat 
      ON dat.EmpID = hr.EmpID 

    WHERE dat.Trainee = 1 
) sub 
GROUP BY location 

我會瞄準第一解決方案,因爲它將更容易維護,並且可能從RDBMS獲得更好的執行路徑並因此更快地運行。雖然......這只是一個猜測。

+0

非常感謝您的幫助! – blacksaibot

2

與JNevill非常相似的第一個答案。但是如果你加入一次冠軍頭銜,你可以檢查並計算你想要的任何頭銜數量。

SELECT 
    loc.Location 
    ,COUNT(CASE WHEN t.[title] = 'XYZ' THEN 1 END) AS XYZ_Trainee_Count 
    ,COUNT(CASE WHEN t.[title] = 'ABC' THEN 1 END) AS ABC_Trainee_Count 

FROM 
    dbo.[n_HRODS] hr 
INNER JOIN dbo.[Locations] loc 
     ON loc.LocationID = hr.LocationID 
INNER JOIN dbo.[EmpData] dat 
     ON dat.EmpID = hr.EmpID 
INNER JOIN dbo.[Titles] t 
     ON hr.SAC = t.[SAC]  
WHERE dat.Trainee = 1 

GROUP BY loc.Location  
+0

啊,有趣。謝謝(你的)信息! – blacksaibot