PostgreSQL WHERE 计数条件

问题描述 投票:0回答:3

我在 PostgreSQL 中有以下查询:

SELECT 
    COUNT(a.log_id) AS overall_count
FROM 
    "Log" as a, 
    "License" as b 
WHERE 
    a.license_id=7 
AND 
    a.license_id=b.license_id 
AND
    b.limit_call > overall_count
GROUP BY 
    a.license_id;

为什么会出现此错误:

错误:列“overall_count”不存在

我的表结构:

License(license_id, license_name, limit_call, create_date, expire_date)
Log(log_id, license_id, log, call_date)

我想检查许可证是否已达到特定月份的调用限制。

sql postgresql group-by having
3个回答
62
投票
SELECT a.license_id, a.limit_call
     , count(b.license_id) AS overall_count
FROM   "License"  a
LEFT   JOIN "Log" b USING (license_id)
WHERE  a.license_id = 7 
GROUP  BY a.license_id  -- , a.limit_call  -- add in old versions
HAVING a.limit_call > count(b.license_id)

自 Postgres 9.1 以来,主键涵盖了

GROUP BY
子句中表的所有列。在旧版本中,您必须将
a.limit_call
添加到
GROUP BY
列表中。 9.1发行说明:

允许非

GROUP BY
列在查询目标列表中,当主 key 在
GROUP BY
子句中指定

延伸阅读:

您在

WHERE
子句中的条件必须移动到
HAVING
子句,因为它指的是聚合函数的结果(after
WHERE
已应用)。并且您不能在 HAVING 子句中引用
output columns
(列别名),您只能在其中引用输入列。所以你必须重复这个表达。 说明书:

输出列的名称可用于引用列中的值

ORDER BY
GROUP BY
从句,但不在
WHERE
HAVING
条款;在那里你必须写出表达式。

我颠倒了

FROM
子句中的表格顺序,并稍微清理了语法以减少混淆。
USING
在这里只是为了方便记号。

我使用了

LEFT JOIN
而不是
JOIN
,所以你根本不会排除没有任何日志的许可证。

count()
只计算非空值。由于您想在表"Log"中计算
相关条目
,因此使用
count(b.license_id)
更安全且稍微便宜一些。这个列在连接中使用,所以我们不必担心列是否可以为空。
count(*)
更短,速度稍快。如果您不介意为左表中的
1
行计算
0
的数量,请使用它。

旁白:如果可能的话,我会建议not在Postgres中使用混合大小写标识符。非常容易出错。


11
投票

纯条件计数(*):

  SELECT COUNT(*) FILTER(where a.myfield > 0) AS my_count
    FROM "Log" as a 

GROUP BY a.license_id

所以你:

  • get
    0
    对于条件永远不满足的组
  • 可以根据需要添加任意数量的 count(*) 列

过滤出条件不匹配的组:

注意:您不能使用

HAVING b.limit_call > ...
,除非您按
limit_call
分组。但是您可以使用聚合函数将组中的许多“limit_calls”映射为单个值。例如,在您的情况下,您可以使用
MAX
:

  SELECT COUNT(a.log_id) AS overall_count
    FROM "Log" as a 
    JOIN "License" b ON(a.license_id=b.license_id)

GROUP BY a.license_id
  HAVING MAX(b.limit_call) > COUNT(a.log_id)

并且不要在意在第一行和最后一行中重复

COUNT(a.log_id)
表达式。 Postgres 会优化它。


10
投票

where
查询无法识别您的列别名,此外,您正在尝试过滤掉after 聚合的行。尝试:

SELECT 
COUNT(a.log_id) AS overall_count
FROM 
"Log" as a, 
"License" as b 
WHERE 
a.license_id=7 
AND 
a.license_id=b.license_id 
GROUP BY 
a.license_id
having b.limit_call > count(a.log_id);

having
子句类似于
where
子句,除了它在聚合之后处理列,而
where
子句在聚合之前处理列。

还有,你的表名用双引号括起来是不是有原因?

© www.soinside.com 2019 - 2024. All rights reserved.