我有这样的查询:
SELECT t1.id,
(SELECT COUNT(t2.id)
FROM t2
WHERE t2.id = t1.id
) as num_things
FROM t1
WHERE num_things = 5;
目标是获取在另一个表中出现5次的所有元素的id。但是,我收到了这个错误:
ERROR: column "num_things" does not exist
SQL state: 42703
我可能在这里做些傻事,因为我对数据库有些新意。有没有办法修复此查询,以便我可以访问num_things
?或者,如果没有,是否还有其他方法可以实现这一结果?
答案 0 :(得分:10)
关于使用SQL的一些要点:
以下是我编写此查询的方式:
SELECT t1.id, COUNT(t2.id) AS num_things
FROM t1 JOIN t2 USING (id)
GROUP BY t1.id
HAVING num_things = 5;
我意识到这个查询可以跳过JOIN
和t1,就像Charles Bretana的解决方案一样。但我假设您可能希望查询包含来自t1的其他一些列。
回复:评论中的问题:
不同之处在于WHERE
子句在行上进行评估,之后GROUP BY
将组减少为每组一行。在组成立后评估HAVING
子句。因此,您无法使用COUNT()
更改群组的HAVING
;你只能排除小组本身。
SELECT t1.id, COUNT(t2.id) as num
FROM t1 JOIN t2 USING (id)
WHERE t2.attribute = <value>
GROUP BY t1.id
HAVING num > 5;
在上面的查询中,WHERE
过滤了与条件匹配的行,HAVING
过滤了至少有五个计数的群组。
导致大多数人混淆的一点是,当他们没有GROUP BY
子句时,似乎就像HAVING
和WHERE
是可以互换的。
WHERE
。这可能并不明显,因为SQL语法首先放置select-list。因此,您可以使用WHERE
限制行来节省大量昂贵的计算。
SELECT <expensive expressions>
FROM t1
HAVING primaryKey = 1234;
如果您使用上述查询,则会为每一行计算select-list中的表达式,但由于HAVING
条件,只会丢弃大部分结果。但是,下面的查询仅计算与WHERE
条件匹配的单行的表达式。
SELECT <expensive expressions>
FROM t1
WHERE primaryKey = 1234;
回顾一下,数据库引擎根据一系列步骤运行查询:
JOIN
生成的所有行。WHERE
条件,过滤掉不匹配的行。GROUP BY
子句,将每个组的一组压缩为一行。HAVING
条件,过滤掉不匹配的群组。ORDER BY
子句对结果进行排序。答案 1 :(得分:3)
所有其他建议都有效,但要回答你的基本问题,写
就足够了 SELECT id From T2
Group By Id
Having Count(*) = 5
答案 2 :(得分:3)
我想提一下,在PostgreSQL中,没有办法在having子句中使用别名列。
即
SELECT usr_id AS my_id FROM user HAVING my_id = 1
不工作。
另一个不起作用的例子:
SELECT su.usr_id AS my_id,COUNT(*)AS val FROM sys_user AS su GROUP BY su.usr_id HAVING val&gt; = 1
会出现同样的错误:val列未知。
我很高兴这是因为Bill Karwin为Postgres写了一些不真实的东西:
“你不能在WHERE子句中使用列别名,但你可以在HAVING子句中使用。这就是你得到错误的原因。”
答案 3 :(得分:1)
我认为您可以像这样重写您的查询:
SELECT t1.id
FROM t1
WHERE (SELECT COUNT(t2.id)
FROM t2
WHERE t2.id = t1.id
) = 5;
答案 4 :(得分:0)
试试这个
SELECT t1.id,
(SELECT COUNT(t2.id) as myCount
FROM t2
WHERE t2.id = t1.id and myCount=5
) as num_things
FROM t1