web-dev-qa-db-ja.com

SQL-左結合によるグループ化

テーブルが2つあります。表Aには、従業員名のリストがあります。表Bは、従業員が行った電話に関する情報を含む複雑な表です。

私の目標は、「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 
12
Brandi

NULLの問題ではなく、JOINです。フィルターがOUTERをINNER JOINに変更しています。これは、必要なOUTER JOINではなく、CallTable(B)に行がある場合にのみCOUNTを取得することを意味します。

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のすべてのフィルターは、外部の場所ではなく、派生テーブルにある必要があります。

33
gbn

LEFT JOINを使用しているため、LEFT JOINで定義されたテーブルへの参照はnullになる可能性があります。行がありますが、カウント値がゼロとして表示されません。つまり、この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標準の手段です。最初の非null値を返しますが、見つからない場合はnullを返します。 [〜#〜] isnull [〜#〜] はSQL Serverでは有効な代替手段ですが、COALESCEが有効な間は他のデータベースに移植できません。これが 2つの関数を比較したMSDNの記事 です。

2
OMG Ponies