如何在COUNT个汇总中包含“零” /“ 0”结果?


112

我刚刚陷入了一些SQL问题。我认为我不能很好地表达问题-所以让我告诉你。

我有两个桌子,一个叫人,一个叫约会。我正在尝试返回一个人的约会数量(包括零个约会)。约会包含person_id和,并且person_id每个约会都有一个。因此COUNT(person_id)是明智的做法。

查询:

SELECT person_id, COUNT(person_id) AS "number_of_appointments" 
FROM appointment 
GROUP BY person_id;

将正确返回person_id拥有的约会数量。但是,约会不为0的人不会返回(显然是因为他们不在该表中)。

调整语句以从人员表中获取person_id可以得到以下信息:

SELECT person.person_id, COUNT(appointment.person_id) AS "number_of_appointments"
FROM appointment
JOIN person ON person.person_id = appointment.person_id
GROUP BY person.person_id;

但是,这仍然只会返回有约会的person_id,而不是我想要的有0个约会的人的返回!

有什么建议吗?


1
如果我想得到零,该怎么办?单表结果为0。我有vm_tool_licenses表,查询如下所示,选择vm_tool_id,从vm_tool_licenses组中计数(vm_tool_license_active),由vm_tool_license_active,vm_tool_id具有vm_tool_license_active = false`
Narendra

Answers:


101

您需要为此使用外部联接(并且需要使用person作为“驱动”表)

SELECT person.person_id, COUNT(appointment.person_id) AS "number_of_appointments"
FROM person 
  LEFT JOIN appointment ON person.person_id = appointment.person_id
GROUP BY person.person_id;

之所以起作用,是因为外部(左)联接将为NULL那些没有约会的人返回。聚合函数count()将不计算NULL值,因此您将得到零。

如果您想了解有关外部联接的更多信息,这是一个不错的教程:http : //sqlzoo.net/wiki/Using_Null


但是,如果约会的某些字段不为空(在表定义中)怎么办?
Lior Yehezkely

@LiorYehezkely:“某些列”无关紧要。count()使用联接列。如果不为空,则应计一次约会
a_horse_with_no_name

21

您必须使用LEFT JOIN而不是INNER JOIN

SELECT person.person_id, COUNT(appointment.person_id) AS "number_of_appointments"
FROM person 
LEFT JOIN appointment ON person.person_id = appointment.person_id
GROUP BY person.person_id;

1
由于查询中不包含表,因此GROUP BY在原始问题中看起来像是错字。
Joachim Isaksson

7

如果执行外部联接(使用count),然后将此结果用作子表,则可以按预期方式获得0(由于nvl函数)

例如:

select P.person_id, nvl(A.nb_apptmts, 0) from 
(SELECT person.person_id
FROM person) P
LEFT JOIN 
(select person_id, count(*) as nb_apptmts
from appointment 
group by person_id) A
ON P.person_id = A.person_id

5

使用GROUP BY通过USE联接获得0计数。

只需简单地使用“ join”就可以在MS SQL中进行内部联接,因此请选择左联接或右联接。

如果在QUERY中首先提到包含主键的表,则使用LEFT联接,否则使用RIGHT联接。

例如:

select WARDNO,count(WARDCODE) from MAIPADH 
right join  MSWARDH on MSWARDH.WARDNO= MAIPADH.WARDCODE
group by WARDNO

select WARDNO,count(WARDCODE) from MSWARDH
left join  MAIPADH on MSWARDH.WARDNO= MAIPADH.WARDCODE group by WARDNO

从具有主键的表中进行分组,并从具有实际条目/明细的另一个表中进行计数。


2

要对原始查询进行更少的更改,您可以将联接变成RIGHT联接

SELECT person.person_id, COUNT(appointment.person_id) AS "number_of_appointments"
FROM appointment
RIGHT JOIN person ON person.person_id = appointment.person_id
GROUP BY person.person_id;

这只是建立在所选答案的基础上,但是随着外部联接的RIGHT发展,只需要添加一个单词,而无需进行太多更改。-请记住,它在那里,有时可以使查询更具可读性,并且需要较少的重建。


0

LEFT JOIN的问题在于,如果没有约会,则它仍将返回一个空值的行,当按COUNT进行汇总时,该行将变为1,并且当该人实际上没有约会时,将显示该人有一个约会。我认为这将给出正确的结果:

SELECT person.person_id,
(SELECT COUNT(*) FROM appointment WHERE person.person_id = appointment.person_id) AS 'Appointments'
FROM person;

我只是要发布相同的解决方案,非常简单。
乔尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.