从没有行的计数中获取 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 如何处理NULLs。即当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_idSELECT 列表中有单个聚合函数。 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 值的主要内容,如果未能解决你的问题,请参考以下文章

如何获得解码/未透视行的唯一计数(列到行)

错误消息(列计数与第 1 行的值计数不匹配)[重复]

Codeigniter 模型出现错误:列计数与第 2 行的值计数不匹配

错误列计数不计算第 1 行的计数 [重复]

如何使用单个查询获取存储在不同变量中的多个表行的计数?

SQL 错误列计数与第 1 行的值计数不匹配