从没有行的计数中获取0值

时间:2011-02-01 17:55:53

标签: sql postgresql select count

我有SELECT:

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);

完美无缺。但是有可能把它写得更简单或者这是最好的解决方案吗?我应该创建任何索引吗?

6 个答案:

答案 0 :(得分:15)

您需要在PostgreSQL http://developer.postgresql.org/pgdocs/postgres/functions-conditional.html

中使用COALESCE功能

基本上你需要告诉SQL如何处理NULL。即当NULL返回0时。

答案 1 :(得分:5)

你不能。

如果您的候选人没有申请,那么您无法阅读他们的candidate_id

如果候选人没有他们在Applications表中,你怎么知道?

在您的示例代码中,没有候选人,因此您不可能说特定候选人没有应用程序。通过这种逻辑,有无数个候选人没有申请。

您需要一份候选人表格才能获得这些信息......除非您打算假设候选人存在,因为您是通过身份证件提出的?

修改

现在你有一个Candidates表,你可以这样做:

SELECT c.ID, (SELECT COUNT(a.*) FROM Applications a WHERE a.candidate_id = c.ID) 
FROM Candidate c
WHERE ....

答案 2 :(得分:2)

也许:

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

答案 3 :(得分:1)

你不能使用这句话:

SELECT count("candidate_id") as c
FROM "Applicaions" WHERE "candidate_id"=_SOME_ID_
GROUP BY "candidate_id"

它应该返回count(),你不需要子查询。

编辑:Matthew PK是正确的,Andy Paton有更好的答案;)

答案 4 :(得分:1)

您可以尝试以下内容(假设您有一个候选表,并且我对表/列名称的假设是正确的。)

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 :(得分:1)

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()吞没。如果要命名结果列,请将别名移到末尾。

  • 对于常规小写标识符,您不需要双引号。

另一个更清洁(IMHO)形式是使用 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表达式更快。<​​/ li>

或者,对于表格中的所有行“候选人”:

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的外键列,因此您最有可能开始使用它。