从没有行的计数中获取 0 值
Posted
技术标签:
【中文标题】从没有行的计数中获取 0 值【英文标题】:Get 0 value from a count with no rows 【发布时间】:2011-06-19 11:10:34 【问题描述】:我有选择:
SELECT c FROM (
SELECT "candidate_id" as id, count("candidate_id") as c
FROM "Applicaions"
GROUP BY "candidate_id"
) as s WHERE id= _SOME_ID_;
但这只会在count > 0
时返回一个值。如果count = 0
它什么也不返回。没有任何申请的“候选人”如何获得0
?
有表“候选人”。 如果候选人没有申请或不存在,我需要得到 0。
编辑
我现在有:
SELECT COALESCE ((SELECT count("candidate_id") as c
FROM "Applicaions" WHERE "candidate_id"=_SOME_ID_
GROUP BY "candidate_id"), 0);
完美运行。但是是否可以更简单地编写它或者这是最好的解决方案?我应该创建任何索引吗?
【问题讨论】:
您需要一个Candidate
表,除非您只想返回带有“零找到”结果或其他内容的查询 ID。
有“候选人”表。没有申请的人怎么能得0?
如果不使用Candidates
表,则有 无限 数量的候选人没有申请... 10001,10002,10003,...99999 无限
【参考方案1】:
你不能。
如果你的候选人没有申请,那么你就没有办法读取他们的candidate_id
值
如果候选人不在Applications
表中,您如何知道他们存在?
在您的示例代码中,没有候选人,因此您不可能说特定候选人的申请数量为零。按照这个逻辑,有无数的候选人有零申请。
您将需要一个候选人表来获取此信息...除非您打算假设某个候选人存在,因为您通过 ID 要求它?
编辑
现在您有了Candidates
表,您可以这样做:
SELECT c.ID, (SELECT COUNT(a.*) FROM Applications a WHERE a.candidate_id = c.ID)
FROM Candidate c
WHERE ....
【讨论】:
【参考方案2】:你不能用这个说法吗:
SELECT count("candidate_id") as c
FROM "Applicaions" WHERE "candidate_id"=_SOME_ID_
GROUP BY "candidate_id"
它应该返回 count() 并且你不需要子查询。
编辑:Matthew PK 是正确的,Andy Paton 有更好的答案;)
【讨论】:
【参考方案3】:需要在PostgreSQL中使用COALESCE函数http://developer.postgresql.org/pgdocs/postgres/functions-conditional.html
基本上你需要告诉 SQL 如何处理NULL
s。即当NULL
返回0
。
【讨论】:
我知道。我删除了它们。只是想告诉我需要 0 值,而不是 '0' 字符串来显示。但是删除 's 是我可以自己解决的问题,而不是加入、触发器等:P。我不太了解 SQL :(【参考方案4】:您可以尝试以下方法(假设您有一个候选表并且我对表/列名称的假设是正确的)。
SELECT c FROM (
SELECT "Candidate"."candidate_id" as id,
count("Applications"."candidate_id") as c
FROM "Candidate" LEFT JOIN "Applications"
ON "Applications"."candidate_id"="Candidate"."id"
GROUP BY "Candidate"."candidate_id" ) as s WHERE id= _SOME_ID_;
【讨论】:
【参考方案5】:也许:
SELECT CASE c WHEN NULL THEN 0 ELSE c END
FROM (
SELECT "candidate_id" as id, count("candidate_id") as c
FROM "Applicaions"
GROUP BY "candidate_id"
) as s WHERE id= _SOME_ID_;
假设“无”真的是NULL
【讨论】:
是的。 “无”为 NULL。你的回答很好,但现在我喜欢 COALESCE :)【参考方案6】:this related one的作者让我知道了这个问题,他在阅读这里后被引导相信他的问题无法解决。嗯,可以的。
这个答案已经快两年了,但最后的问题仍然悬而未决。
查询
是否可以写得更简单或者这是最好的解决方案?
要测试一个单一 ID,您找到的查询很好。你可以简化:
SELECT coalesce((SELECT count(candidate_id)
FROM "Applications" WHERE candidate_id = _SOME_ID_), 0) AS c;
WHERE
条件限制为单个 candidate_id
,SELECT
列表中有单个聚合函数。 GROUP BY candidate_id
是多余的。
列别名被COALESCE()
吞噬。如果要命名结果列,请将别名移到末尾。
另一种更简洁(恕我直言)的形式是使用 LEFT JOIN
:
SELECT count(a.candidate_id) AS c
FROM (SELECT _SOME_ID_ AS candidate_id) x
LEFT JOIN "Applicaions" a USING (candidate_id)
这也适用于多个 ID:
WITH x(candidate_id) AS (
VALUES
(123::bigint)
,(345)
,(789)
)
SELECT x.candidate_id, count(a.candidate_id) AS c
FROM x
LEFT JOIN "Applicaions" a USING (candidate_id)
GROUP BY x.candidate_id;
对于长列表,LEFT JOIN
通常比多个 WHERE
子句或 IN
表达式更快。
或者,对于表格中的所有行“候选人”:
SELECT x.candidate_id, count(a.candidate_id) AS c
FROM "Candidates" x
LEFT JOIN "Applications" a USING (candidate_id)
GROUP BY x.candidate_id;
索引
我应该创建任何索引吗?
如果读取性能很重要,并且表包含的不仅仅是几行,那么您肯定需要以下形式的索引:
CREATE INDEX foo_idx ON "Applications" (candidate_id);
由于这似乎是一个引用 "Candidates".candidate_id
的外键列,您很可能应该从它开始。
【讨论】:
以上是关于从没有行的计数中获取 0 值的主要内容,如果未能解决你的问题,请参考以下文章