2010-07-12 110 views
8

我有兩個表。表A列出了員工姓名。表B是一個複雜的表格,其中包含員工打電話的信息。SQL - 按左連接分組

我的目標是創建一個列'name'和'callCount'的表。我打算通過「左連接」和「分組」來實現這一點,但我一直在思念那些沒有打過電話的員工。我怎樣才能讓它保持名稱,並在那裏放一個零?

也許我很近,有人可以指出我的錯字?在此先感謝您的幫助,這裏是SQL:

SELECT A.name, COUNT(B.call_id) AS 'outgoing call count' 
FROM EmployeeTable A 
LEFT JOIN CallTable B 
ON A.name = B.call_from_name 
WHERE B.call_type LIKE 'outgoing' 
AND B.voice_mail = '0' 
... 
GROUP BY A.name 

回答

25

這是一個JOIN不是NULL問題:您的過濾器將OUTER更改爲INNER JOIN。這意味着你只有在CallTable(B)中有行的地方纔能得到COUNT,而不是你想要的OUTER JOIN。

SELECT A.name, COUNT(B.call_id) AS 'outgoing call count' 
FROM 
    EmployeeTable A 
    LEFT JOIN 
    (
    SELECT call_from_name, call_id FROM CallTable 
    WHERE call_type LIKE 'outgoing' 
    AND voice_mail = '0' 
    AND /* other CallTable filters */ 
    ) B 
    ON A.name = B.call_from_name 
WHERE 
    /* only EmployeeTable A filters */ 
GROUP BY A.name 

編輯:您的評論別處後,你對所有B中的過濾器必須在派生表,而不是在外部哪裏。

+0

太好了,非常感謝! :) – Brandi 2010-07-12 20:35:26

+3

當你不需要通配符比較時,要小心使用LIKE。它可以真正殺死你的查詢速度。只是做一個常規的平等比較:WHERE call_type ='傳出' – 2010-07-12 20:48:19

+2

有關進一步解釋: http://wiki.lessthandot.com/index.php/WHERE_conditions_on_a_LEFT_JOIN – HLGEM 2010-07-12 21:44:39

2

由於您使用的是LEFT JOIN,在左側定義表中引用JOIN可以爲空。行在那裏,你只是沒有看到計數值爲零。你需要這意味着這個NULL值轉換爲零(在這種情況下):

SELECT A.name, 
      COALESCE(COUNT(B.call_id), 0) AS 'outgoing call count' 
    FROM EmployeeTable A 
LEFT JOIN CallTable B ON B.call_from_name = A.name 
        AND B.call_type LIKE 'outgoing' 
        AND B.voice_mail = '0' 
    WHERE ... 
GROUP BY A.name 

這個例子使用COALESCE,處理NULL值的ANSI標準方法。它將返回第一個非空值,但如果找不到任何值,它將返回空值。 ISNULL是SQL Server上的有效替代方案,但在COALESCE時它不能移植到其他數據庫。這裏是an MSDN article comparing the two functions

+0

COALESCE不需要:它是B上的WHERE子句過濾器使其成爲INNER JOIN – gbn 2010-07-12 20:29:11

+0

我試過ISNULL和COALESCE,兩者都給出相同的結果。我可能會做一些其他的錯誤?我列出的條款比我列出的要多,但它們都是確定計數所必需的。 – Brandi 2010-07-12 20:31:53