几个要点有关使用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
条款排序结果。
哦,我应该重新阅读目标。你是对的。起初,我是这样说的,“但是你失去了伯爵的信息,如果你需要这些信息呢?” – Kev 2009-01-08 22:16:57
是的,那是有效的。奇怪的是,我以为我一开始就尝试过,但得到了“不允许在where子句中允许的聚合”或其他内容。我一定做了一些不同的事情。 是否有一个原因,我张贴的方式不起作用,但? – Claudiu 2009-01-08 22:17:01
我找不到它,但是在新闻组中有一个关于此的线程,并且有一个原因。我能记得的只有一个人说过(如果你重复了这个功能),在大多数情况下,计算两次的开销非常小。 – Kev 2009-01-08 22:20:54