web-dev-qa-db-ja.com

左結合で結合された行の数を数える

テーブル内の特定のレコードに結合されたすべてのレコードのカウントを返す集計クエリをSQLで記述しようとしています。特定のレコードに結合されたレコードがない場合、そのレコードの結果は_0_になります。

データ

私のデータベースは次のようになります(残念ながら、構造を変更することはできません):

_MESSAGE
----------------------------------------------
MESSAGEID   SENDER        SUBJECT
----------------------------------------------
1           Tim           Rabbit of Caerbannog
2           Bridgekeeper  Bridge of Death

MESSAGEPART
----------------------------------------------
MESSAGEID   PARTNO        CONTENT
----------------------------------------------
1           0             (BLOB)
1           1             (BLOB)
3           0             (BLOB)
_

MESSAGEPARTには複合PRIMARY KEY("MESSAGEID", "PARTNO")があります)

望ましい出力

上記のデータを考えると、次のようになります。

_MESSAGEID   COUNT(*)
-----------------------------------------------
1           2
2           0
_

MESSAGEテーブルで左結合を行う必要があることは明らかなようですが、MESSAGEPARTの結合列がNULLである行に対して_0_のカウントを返すにはどうすればよいですか?私は次を試しました:

論理

私はもう試した

_SELECT m.MESSAGEID, COUNT(*) FROM MESSAGE m
LEFT JOIN MESSAGEPART mp ON mp.MESSAGEID = m.MESSAGEID
GROUP BY m.MESSAGEID;
_

ただし、これは戻ります

_MESSAGEID   COUNT(*)
-----------------------------------------------
1           2
2           1
_

私も試しました

_SELECT mp.MESSAGEID, COUNT(*) FROM MESSAGE m
LEFT JOIN MESSAGEPART mp ON mp.MESSAGEID = m.MESSAGEID
GROUP BY mp.MESSAGEID;
_

しかし、これは戻ります

_MESSAGEID   COUNT(*)
-----------------------------------------------
1           2
            1
_

ここで何が間違っていますか?

30
errantlinguist

このようなものはどうですか:

SELECT m.MESSAGEID, sum((case when mp.messageid is not null then 1 else 0 end)) FROM MESSAGE m
LEFT JOIN MESSAGEPART mp ON mp.MESSAGEID = m.MESSAGEID
GROUP BY m.MESSAGEID;

COUNT()関数は、NULLがある場合でも、すべての行をカウントします。 SUM()およびCASEを使用すると、null以外の値のみをカウントできます。

編集:トップコメントから取られたよりシンプルなバージョン:

SELECT m.MESSAGEID, COUNT(mp.MESSAGEID) FROM MESSAGE m
LEFT JOIN MESSAGEPART mp ON mp.MESSAGEID = m.MESSAGEID
GROUP BY m.MESSAGEID;

お役に立てば幸いです。

51
Mark J. Bobak

first参加する前に、メッセージテーブルで数えたいと思います。これを試して:

   SELECT m.MessageId
        , COALESCE(c, 0) as myCount
     FROM MESSAGE m
LEFT JOIN (SELECT MESSAGEID
                , count(*) c 
             FROM MESSAGEPART 
            GROUP BY MESSAGEID) mp
       ON mp.MESSAGEID = m.MESSAGEID
9
oerkelens