计算左连接中连接行的数量

err*_*ist 31 sql oracle join count left-join

我正在尝试在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)
Run Code Online (Sandbox Code Playgroud)

(MESSAGEPART有一个复合PRIMARY KEY("MESSAGEID", "PARTNO"))

期望的输出

鉴于上面的数据我应该得到这样的东西:

MESSAGEID   COUNT(*)
-----------------------------------------------
1           2
2           0
Run Code Online (Sandbox Code Playgroud)

它似乎很明显,我需要做的左连接的MESSAGE表,但我怎么回的计数0为行,其中联接的列从MESSAGEPARTNULL?我尝试过以下方法:

逻辑

我试过了

SELECT m.MESSAGEID, COUNT(*) FROM MESSAGE m
LEFT JOIN MESSAGEPART mp ON mp.MESSAGEID = m.MESSAGEID
GROUP BY m.MESSAGEID;
Run Code Online (Sandbox Code Playgroud)

但是,这会回来

MESSAGEID   COUNT(*)
-----------------------------------------------
1           2
2           1
Run Code Online (Sandbox Code Playgroud)

我也试过了

SELECT mp.MESSAGEID, COUNT(*) FROM MESSAGE m
LEFT JOIN MESSAGEPART mp ON mp.MESSAGEID = m.MESSAGEID
GROUP BY mp.MESSAGEID;
Run Code Online (Sandbox Code Playgroud)

但这会回来

MESSAGEID   COUNT(*)
-----------------------------------------------
1           2
            1
Run Code Online (Sandbox Code Playgroud)

我在这做错了什么?

Mar*_*bak 56

这样的事情怎么样:

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;
Run Code Online (Sandbox Code Playgroud)

COUNT()函数将计算每一行,即使它为null.使用SUM()和CASE,您只能计算非空值.

编辑:从顶部评论中获取的更简单的版本:

SELECT m.MESSAGEID, COUNT(mp.MESSAGEID) FROM MESSAGE m
LEFT JOIN MESSAGEPART mp ON mp.MESSAGEID = m.MESSAGEID
GROUP BY m.MESSAGEID;
Run Code Online (Sandbox Code Playgroud)

希望有所帮助.

  • 它可以简化一点.`sum(case .... end)`可以用简单的`count(mp.messageid)`替换.`Count(*)`计数,好吧,所有东西,包括空值和`count(col_name)`只计算非空值. (8认同)

oer*_*ens 9

在我加入之前,你首先想要计算你的messaepart表.试试这个:

   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
Run Code Online (Sandbox Code Playgroud)


小智 9

如果您要 LEFT JOIN 多个表,请不要忘记使用DISTINCT :

SELECT m.MESSAGEID, COUNT(DISTINCT mp.MESSAGEID) FROM MESSAGE m
LEFT JOIN MESSAGEPART mp ON mp.MESSAGEID = m.MESSAGEID
GROUP BY m.MESSAGEID;
Run Code Online (Sandbox Code Playgroud)