2016-09-30 44 views
1

我怎樣才能重新編寫,以便它不會觸發以下錯誤此查詢:「不能對包含聚合或子查詢的表達式執行聚合函數」SUM使用CASE時選擇

SELECT 
    employees.loc_id 
    ,SUM(CASE 
      WHEN 
       pos IN (SELECT DISTINCT pos FROM lookup WHERE lbl='Staff') 
      AND 
       loc IN (SELECT DISTINCT loc FROM lookup WHERE lbl='Staff') 
      THEN 1 
      ELSE 0 
     END) AS 'Staff Site 1' 
    ,SUM(CASE 
      WHEN 
       pos IN (SELECT DISTINCT pos FROM table WHERE lbl='Staff') 
      AND 
       loc IN (SELECT DISTINCT loc FROM table WHERE lbl='Staff') 
      THEN 1 
      ELSE 0 
     END) AS 'Staff Site 2' 

FROM table GROUP BY table.key_id ORDER BY key_id 

因此很明顯,我不能把內SUM一個SELECT聲明?我如何確保我只是在總結上述代碼中描述的情況?

pos確定位置的類型。 loc決定在什麼地點(位置)。查找表的結構是這樣的:

pos | loc | lbl 
123 | XYZ | Staff Site 1 
456 | XYZ | Staff Site 1 
987 | XYZ | Supervisor Site 1 
123 | ABC | Staff Site 2 
123 | JKL | Staff Site 3 
123 | OPQ | Staff Site 4 
456 | OPQ | Staff Site 4 
345 | OPQ | Staff Site 4 

該查找表只是確定與特定位置處的位置關聯的標籤。

有一張員工表,每個員工分配一個職位#。

,所以我想我的查詢從僱員表中選擇所有loc_id(位置ID),併爲每個loc_id,總結查找表

所以,如果我有30名員工與loc_id=XYZpos=123相應條目和20名員工與loc_id=XYZpos=456,輸出將提前

loc_id | Staff Site 1 
XYZ | 50 

謝謝,我希望這不是太混亂...

回答

4

沒有進入技術來避開能夠在聚合函數內部進行SELECT操作。讓我們退後一步,重新審視您的查詢。您試圖通過聚合Lookup表來解決它,但聚合實際上是在來自查找表的連接的Employee表上。

它也似乎是你正在嘗試做有條件的聚合到你的結果。但無論哪種情況,如果你做下面的,如果你做下面你會得到你指定結果:

SELECT 
    l.loc 
    ,COUNT(DISTINCT e.Id) as EmployeesAtStaffSite1 
FROM 
    Lookup l 
    INNER JOIN Employees e 
    ON e.loc = l.loc 
    AND e.pos = l.pos 
WHERE 
    l.lbl = 'Staff Site 1' 
GROUP BY 
    l.loc 

另外請注意,如果你改變INNER JOIN左連接,你可以得到0計數作爲任何位置員工場所1表示沒有員工分配。

+2

我懷疑這返回了OP想要返回的結果,但很難確定確切的規格。 「讓我們從鍵盤上移開手指,慢慢退開,然後*思考*我們正在努力實現的目標,以及如何解釋它......」 – spencer7593

+0

輝煌的馬特。謝謝。 – blacksaibot

0

這樣做的一種方法(假設你真的需要這樣做)就是將聚合放在一個外部查詢中,並將其包裝在條件內(即,子查詢),如下所示:

select key_id, sum(staff_site_1) as staff_site_1, , sum(staff_site_2) as staff_site_2 
from (
    SELECT 
    employees.key_id 
    ,CASE 
     WHEN 
      pos IN (SELECT DISTINCT pos FROM lookup WHERE lbl='Staff') 
     AND 
      loc IN (SELECT DISTINCT loc FROM lookup WHERE lbl='Staff') 
     THEN 1 
     ELSE 0 
    END AS staff_site_1 
    ,CASE 
     WHEN 
      pos IN (SELECT DISTINCT pos FROM lookup WHERE lbl='Staff') 
     AND 
      loc IN (SELECT DISTINCT loc FROM lookup WHERE lbl='Staff') 
     THEN 1 
     ELSE 0 
    END AS staff_site_2 
    FROM table 
) x 
GROUP BY key_id 
ORDER BY key_id 
0
; with _CTE as (
SELECT 
    employees.loc_id 
    ,CASE 
      WHEN 
       pos IN (SELECT DISTINCT pos FROM lookup WHERE lbl='Staff') 
      AND 
       loc IN (SELECT DISTINCT loc FROM lookup WHERE lbl='Staff') 
      THEN 1 
      ELSE 0 
     END AS StaffSite1 
    ,CASE 
      WHEN 
       pos IN (SELECT DISTINCT pos FROM table WHERE lbl='Staff') 
      AND 
       loc IN (SELECT DISTINCT loc FROM table WHERE lbl='Staff') 
      THEN 1 
      ELSE 0 
     END AS StaffSite2 

FROM table 
) 
SELECT 
    loc_id 
    ,SUM(StaffSite1) AS 'Staff Site 1' 
    ,SUM(StaffSite2) AS 'Staff Site 2' 

FROM _CTE GROUP BY loc_id ORDER BY loc_id 

說明:的_CTE是臨時結果集,其在這裏被施加CASE條件的數據。然後你在這個結果集上運行聚合函數。

+0

cte不是一個臨時表,它是一個表達式。把它想象成一種定義派生表的方式,而不需要在最終的select語句中包含所有額外的代碼。它是一個在單個SELECT的執行分數內定義的臨時結果集......所以當你定義它時,它將不會被執行,而是在關於使用它的最終語句中執行它。 https://technet.microsoft.com/en-us/library/ms190766(v=sql.105).aspx – Matt

+1

謝謝馬特。我修改了我的答案以糾正錯誤。 – Sparrow

+0

感謝您的幫助。 – blacksaibot

1

外部查詢引用表名稱table,但SELECT列表中的列使用employees.限定。該查詢執行GROUP BY table.key_id,但SELECT列表中返回的列名爲loc_id。兩個子查詢都在尋找與文字'Staff'匹配的lbl,第一組查找表名爲lookup。我們在lookup表中看不到任何示例行,其中該條件將評估爲true。在第二組中,子查詢引用了不同的表格(不幸命名爲)table

很難說出你實際試圖用這個查詢來完成什麼。

令人困惑的是,問題的最後一部分表明您需要結果集中包含兩列,員工表中的值爲loc_id。還有一些聚合列包含滿足一些標準的行數...

loc_id Staff Site 1 
------ ------------ 
XYZ    50 

讓我們備份幾個步驟。

看起來您希望查看employee表中的所有行,並且您只關注表中的三列或四列。這是您要分析的行和列的集合。 (目前尚不清楚,無論您是需要從table表引用一個名爲lbl柱,一組引用的table,而不是lookup子查詢使它看起來像這樣的話。

所以,首先是行的集合您想查詢一下......

SELECT e.loc_id 
     , e.pos 
     , e.loc 
    FROM employee e 

從這一點,你想要得到的loc_id不同的值。而且你要通過添加GROUP BY子句來實現這一目標。

我們可以很容易獲得所有ro的「計數」 ws在與每個loc_id有關的僱員使用一個聚合,COUNT(*)。但是你有興趣只能得到符合特定標準的員工......有條件的聚合。如果(loc_id,pos)的組合在查找表中是UNIQUE, (示例數據使其看起來像是這樣,但由於在有限的示例數據中沒有反例,我們無法確定)...

如果這是唯一的,我們可以對該表執行JOIN操作,以「查找」與每個員工的(loc_id,pos)相關的lbl

SELECT e.loc_id 
     , e.pos 
     , e.loc 
     , l.lbl 
    FROM employee e 
    LEFT 
    JOIN lookup l 
    ON l.loc_id = e.loc_id 
    AND l.pos = e.pos 

如果我想在那個用一排lookup相關與Staff Site 1一個lbl值給定的位置員工人數的計數,我會傾向於寫的......

SELECT e.loc_id 
     , SUM(CASE WHEN l.lbl = 'Staff Site 1' THEN 1 ELSE 0 END) AS [Staff Site 1] 
    FROM employee e 
    LEFT 
    JOIN lookup l 
    ON l.loc_id = e.loc_id 
    AND l.pos = e.pos 
    GROUP BY e.loc_id 
    ORDER BY e.loc_id 

如果我想第二列,並數「網站的工作人員2」

SELECT e.loc_id 
     , SUM(CASE WHEN l.lbl = 'Staff Site 1' THEN 1 ELSE 0 END) AS [Staff Site 1] 
     , SUM(CASE WHEN l.lbl = 'Staff Site 2' THEN 1 ELSE 0 END) AS [Staff Site 2] 
    FROM employee e 
    LEFT 
    JOIN lookup l 
    ON l.loc_id = e.loc_id 
    AND l.pos = e.pos 
    GROUP BY e.loc_id 
    ORDER BY e.loc_id 

如果我沒有具體的需要「支點「結果,我可以更簡單地運行一個返回單獨行的查詢,對於給定loc_id處的每個employee的每個值lbl

SELECT e.loc_id AS loc_id 
     , e.lbl  AS lbl 
     , SUM(1) AS cnt 
    FROM employee e 
    LEFT 
    JOIN lookup l 
    ON l.loc_id = e.loc_id 
    AND l.pos = e.pos 
    GROUP BY e.loc_id 
    ORDER BY e.loc_id 
+0

非常感謝您的詳細解釋和故障。 – blacksaibot

0

我沒有看到任何你正在打的employees.loc_id但它是在選擇。相反,您只有GROUP BY table.key_id ORDER BY key_id