49

我在 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)

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

4

3 回答 3

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

GROUP BY从 Postgres 9.1 开始,主键覆盖子句中表的所有列。在旧版本中,您必须添加a.limit_callGROUP BY列表中。9.1的发行说明

子句GROUP BY中指定主键时,允许查询目标列表中的非列GROUP BY

进一步阅读:

您在WHERE子句中的条件必须移至HAVING子句,因为它引用聚合函数的结果(after WHERE已应用)。并且您不能在子句中引用输出列(列别名)HAVING,您只能引用输入列。所以你必须重复表达。手册:

输出列的名称可用于在 ORDER BYandGROUP BY子句中引用列的值,但不能在WHEREorHAVING 子句中;在那里你必须写出表达式。

我颠倒了子句中表的顺序FROM并稍微清理了语法以减少混乱。USING在这里只是一个符号上的方便。

我使用LEFT JOIN而不是JOIN,因此您根本不会排除没有任何日志的许可证。

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

另外:如果可能,我建议不要在 Postgres中使用混合大小写标识符。非常容易出错。

于 2011-11-14T09:54:02.170 回答
10

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

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子句处理聚合之前的列。

另外,你的表名用双引号括起来有什么原因吗?

于 2011-11-14T09:32:33.313 回答
5

纯条件计数(*):

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

GROUP BY a.license_id

那么你:

  • 获取0条件从未满足的组
  • 可以根据需要添加任意数量的 count(*) 列

过滤出条件不匹配的组:

注意:您不能使用HAVING b.limit_call > ...,除非您按 分组limit_call。但是您可以使用 agregate 函数将组中的许多“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 会对其进行优化。

于 2020-08-26T20:36:49.387 回答