2009-01-08 93 views
1

我有这样的查询: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?或者,如果没有,是否有其他方法来实现这一结果?

回答

1

我想你可以只重写查询,如下所示:

SELECT t1.id 
FROM t1 
WHERE (SELECT COUNT(t2.id) 
    FROM t2 
    WHERE t2.id = t1.id 
     ) = 5; 
+0

哦,我应该重新阅读目标。你是对的。起初,我是这样说的,“但是你失去了伯爵的信息,如果你需要这些信息呢?” – Kev 2009-01-08 22:16:57

+0

是的,那是有效的。奇怪的是,我以为我一开始就尝试过,但得到了“不允许在where子句中允许的聚合”或其他内容。我一定做了一些不同的事情。 是否有一个原因,我张贴的方式不起作用,但? – Claudiu 2009-01-08 22:17:01

+0

我找不到它,但是在新闻组中有一个关于此的线程,并且有一个原因。我能记得的只有一个人说过(如果你重复了这个功能),在大多数情况下,计算两次的开销非常小。 – Kev 2009-01-08 22:20:54

10

几个要点有关使用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条款,所以它似乎HAVINGWHERE是可以互换的。

WHERE在选择列表中的表达式之前被评估。这可能并不明显,因为SQL语法首先将选择列表放入。因此,通过使用WHERE来限制行,您可以节省大量昂贵的计算。

SELECT <expensive expressions> 
FROM t1 
HAVING primaryKey = 1234; 

如果您使用查询像上面,在选择列表中的表达式计算为每一行,只能放弃大部分因为HAVING条件的结果。但是,下面的查询仅计算与WHERE条件匹配的单行的表达式。

SELECT <expensive expressions> 
FROM t1 
WHERE primaryKey = 1234; 

因此,为了概括,查询由数据库引擎根据一系列的步骤运行:

  1. 生成表(一个或多个)中设置的行,包括由JOIN产生的任何行。
  2. 针对该组行计算WHERE条件,过滤掉不匹配的行。
  3. 在选择列表中为每组行中的每个计算表达式。
  4. 应用列别名(注意这是一个单独的步骤,这意味着您不能在选择列表中的表达式中使用别名)。
  5. 根据GROUP BY条款,将组缩减为每个组的单个行。
  6. 评估HAVING针对组的条件,过滤掉不匹配的组。
  7. 根据ORDER BY条款排序结果。
3

所有其他建议会的工作,而是要回答你的基本的问题就足够写

SELECT id From T2 
    Group By Id 
    Having Count(*) = 5 
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 
3

我想提一提,在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子句中这是你得到了错误的原因。 “