我在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)
我想检查许可证是否已达到特定月份的通话限制。
答案 0 :(得分:45)
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)
在PostgreSQL 9.1之前的版本中,您必须将limit_call
添加到 GROUP BY
子句中。
从版本9.1开始,在GROUP BY
子句中使用主键就足够了。 release notes for 9.1:
主要时,在查询目标列表中允许非
中指定GROUP BY
列 key在GROUP BY
子句
您的WHERE
条件必须移至 HAVING
子句,因为它引用了聚合函数的结果。并且您不能在HAVING
子句中引用输出列(列别名),其中您只能引用输入列。所以你必须重复表达。 Per documentation:
输出列的名称可用于引用列的值
ORDER BY
和GROUP BY
条款,但不在WHERE
或HAVING
条款中; 那里你必须写出表达式。
我颠倒了FROM
子句中表的顺序,并稍微清理了语法,使其不那么混乱。 USING
在这里只是一种符号方便。
我使用 LEFT JOIN
代替JOIN
,因此您根本不会排除没有任何日志的许可。
如果可能,我建议不在Postgres中使用mixed case identifiers。非常容易出错。
count()
仅计算非空值。由于您要在表"Log"
中计算相关条目,因此使用 count(b.license_id)
会更安全且更便宜。此列用于连接,因此我们无需担心列是否为空
count(*)
更短,速度更快。如果您不介意在左表中为1
行计算0
,请使用它。
答案 1 :(得分: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);
having
子句与where
子句类似,不同之处在于它处理聚合后的列,而where
子句在聚合之前处理列。
另外,您的表名是否有用双引号括起来的原因?
答案 2 :(得分:2)
SELECT COUNT(*) FILTER(where a.myfield > 0) AS my_count
FROM "Log" as a
GROUP BY a.license_id
所以你:
0
注意:除非使用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将对其进行优化。