PostgreSQL - 相关的子查询失败?
我有这样的查询:PostgreSQL - 相关的子查询失败?
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
?或者,如果没有,是否有其他方法来实现这一结果?
我想你可以只重写查询,如下所示:
SELECT t1.id
FROM t1
WHERE (SELECT COUNT(t2.id)
FROM t2
WHERE t2.id = t1.id
) = 5;
几个要点有关使用SQL:
- 在WHERE子句中不能使用列别名,但你可以在HAVING条款。这是你得到的错误的原因。
- 您可以使用JOIN和GROUP BY比使用相关子查询更好地进行计算。它会更快。
- 使用HAVING子句过滤组。
这里是我会写这个查询的方式:我知道这个查询可以跳过JOIN
与T1,如查尔斯BRETANA的解决方案
SELECT t1.id, COUNT(t2.id) AS num_things
FROM t1 JOIN t2 USING (id)
GROUP BY t1.id
HAVING num_things = 5;
。但我想你可能希望查询包含来自t1的其他列。
回复:在注释的问题:
的区别在于,WHERE
子句上行评价,GROUP BY
减少组每组单个行之前。在组形成后评估HAVING
子句。因此,例如,您不能通过使用HAVING
更改组的COUNT()
;你只能排除组本身。
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语法首先将选择列表放入。因此,通过使用WHERE
来限制行,您可以节省大量昂贵的计算。
SELECT <expensive expressions>
FROM t1
HAVING primaryKey = 1234;
如果您使用查询像上面,在选择列表中的表达式计算为每一行,只能放弃大部分因为HAVING
条件的结果。但是,下面的查询仅计算与WHERE
条件匹配的单行的表达式。
SELECT <expensive expressions>
FROM t1
WHERE primaryKey = 1234;
因此,为了概括,查询由数据库引擎根据一系列的步骤运行:
- 生成表(一个或多个)中设置的行,包括由
JOIN
产生的任何行。 - 针对该组行计算
WHERE
条件,过滤掉不匹配的行。 - 在选择列表中为每组行中的每个计算表达式。
- 应用列别名(注意这是一个单独的步骤,这意味着您不能在选择列表中的表达式中使用别名)。
- 根据
GROUP BY
条款,将组缩减为每个组的单个行。 - 评估
HAVING
针对组的条件,过滤掉不匹配的组。 - 根据
ORDER BY
条款排序结果。
所有其他建议会的工作,而是要回答你的基本的问题就足够写
SELECT id From T2
Group By Id
Having Count(*) = 5
试试这个
SELECT t1.id,
(SELECT COUNT(t2.id) as myCount
FROM t2
WHERE t2.id = t1.id and myCount=5
) as num_things
FROM t1
我想提一提,在PostgreSQL的在子句中无法使用别名列。
即
SELECT usr_id AS添加my_id FROM用户HAVING添加my_id = 1
不会工作。
是行不通又如:
SELECT su.usr_id AS添加my_id,COUNT(*)AS VAL FROM sys_user苏GROUP BY su.usr_id HAVING值> = 1
会有是相同的错误:val列未知。
林highliting这是因为比尔Karwin写的东西Postgres的不是真的。
“你不能在WHERE子句中使用列别名,但你可以在HAVING子句中这是你得到了错误的原因。 “
哦,我应该重新阅读目标。你是对的。起初,我是这样说的,“但是你失去了伯爵的信息,如果你需要这些信息呢?” – Kev 2009-01-08 22:16:57
是的,那是有效的。奇怪的是,我以为我一开始就尝试过,但得到了“不允许在where子句中允许的聚合”或其他内容。我一定做了一些不同的事情。 是否有一个原因,我张贴的方式不起作用,但? – Claudiu 2009-01-08 22:17:01
我找不到它,但是在新闻组中有一个关于此的线程,并且有一个原因。我能记得的只有一个人说过(如果你重复了这个功能),在大多数情况下,计算两次的开销非常小。 – Kev 2009-01-08 22:20:54