PostgreSQL在哪里计算条件

Had*_*adi 33 sql postgresql group-by having

我在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;
Run Code Online (Sandbox Code Playgroud)

为什么我会收到此错误:

错误:列"overall_count"不存在

我的表结构:

License(license_id, license_name, limit_call, create_date, expire_date)
Log(log_id, license_id, log, call_date)
Run Code Online (Sandbox Code Playgroud)

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

Erw*_*ter 47

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)
Run Code Online (Sandbox Code Playgroud)

主要观点

  • 在PostgreSQL 9.1之前的版本中,您必须添加limit_call到该GROUP BY子句中.从版本9.1开始,在GROUP BY子句中使用主键就足够了.9.1发行说明:

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

  • 您的WHERE条件必须移动到HAVING子句,因为它引用了聚合函数的结果.并且您不能在子句中引用输出列(列别名)HAVING,其中您只能引用输入列.所以你必须重复表达.每个文件:

    输出列的名称可用于引用列的值in ORDER BYGROUP BY子句,但不能用于WHEREHAVING子句; 那里你必须写出表达式.

  • 我颠倒了FROM子句中表的顺序,并稍微清理了语法,使其不那么混乱.USING这里只是一个标志性的便利.

  • 我使用的是LEFT JOIN代替JOIN,因此您根本不排除没有任何日志的许可证.

  • 如果可能的话,我建议不要在Postgres中使用混合大小写标识符.非常容易出错.

  • 只计算非空值count().由于您想要计算中的相关条目,"Log"因此使用起来更安全且更便宜count(b.license_id).此列用于连接,因此我们无需担心列是否为null.
    count(*)更短,更快,但更快.如果您不介意在左表中1获取0行数,请使用它.


epo*_*pox 21

纯条件计数(*):

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

GROUP BY a.license_id
Run Code Online (Sandbox Code Playgroud)

那么你:

  • 获取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)
Run Code Online (Sandbox Code Playgroud)

并且不关心COUNT(a.log_id)第一行和最后一行中的重复表达式。Postgres 会对其进行优化。


小智 6

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);
Run Code Online (Sandbox Code Playgroud)

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

另外,您的表名是否用双引号括起来?