145

我刚刚让自己有点被一些 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 表中获取 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 个约会的人!

请问有什么建议吗?

4

6 回答 6

119

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

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

于 2013-02-10T00:04:21.857 回答
23

您必须使用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;
于 2013-02-10T00:03:44.603 回答
7

如果您进行外连接(使用计数),然后将此结果用作子表,则可以按预期得到 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
于 2016-01-20T13:30:11.080 回答
5

USE join 使用 GROUP BY 在结果中获得 0 个计数。

只需“加入”就可以在 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

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

于 2017-11-09T10:55:52.813 回答
4

要对原始查询进行更少的更改,您可以将联接变成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方向,因此只需要添加一个单词并且更改较少。- 只要记住它就在那里,有时可以使查询更具可读性并且需要更少的重建。

于 2018-06-28T12:21:24.663 回答
3

LEFT JOIN 的问题是,如果没有约会,它仍然会返回一个空行,当按 COUNT 聚合时会变为 1,并且看起来这个人有一个约会,而实际上他们没有约会。我认为这将给出正确的结果:

SELECT person.person_id,
(SELECT COUNT(*) FROM appointment WHERE person.person_id = appointment.person_id) AS 'Appointments'
FROM person;
于 2019-10-10T02:19:09.697 回答