MySQL中的分组JOIN查询 - 使用ON与HAVING条件进行过滤(任何差异?)

时间:2012-09-24 02:50:26

标签: mysql join filtering

以下是伪查询,所以我不关心结果,但是在以下MySQL查询之间是否存在任何差异(性能,结果数量等)?

查询1

SELECT u.`username`, COUNT(*) AS 'posts', u.`age`
FROM `users` u
INNER JOIN `posts` p
ON p.`user_id`=u.`id`
GROUP BY u.`id`
HAVING u.`age` > 12

假设此查询中的列smth仅为了HAVING条件而被选中,因此结果中不需要其值。

查询2

SELECT u.`username`, COUNT(*) AS 'posts'
FROM `users` u
INNER JOIN `posts` p
ON p.`user_id`=u.`id` AND u.`age` > 12
GROUP BY u.`id`

2 个答案:

答案 0 :(得分:2)

总是在完成所有JOIN和WHERE过滤器后完成HAVING。它本质上是对查询结果的过滤器。这就是为什么你不能用它来过滤不属于查询的字段的原因。

您的查询将以不同方式执行。查询2将更有效,因为它将在JOIN期间过滤掉用户。查询1将与所有用户连接,提取所有数据并对其进行分组,然后按年龄对其进行过滤。查询2将GROUP和仅过滤12岁以下的用户,然后对其进行GROUP。需要在查询2中读取和分组较少的数据。

答案 1 :(得分:1)

您的查询完全不同。特别是,第二种是有效的标准SQL语法。第一个使用MySQL功能,允许聚合中允许任何列。

特别是,第一个查询中的列smth来自匹配数据中的任意行。如果所有行的所有值都相同,则两者的结果将是等效的。

如果我假设u.id对于用户中的每一行都是唯一的,那么结果集是等价的。但是,我认为更可读的SQL版本是:

SELECT u.`username`, COUNT(*) AS 'posts', u.`smth`
FROM `users` u  INNER JOIN
     `posts` p 
     ON p.`user_id`=u.`id`
WHERE u.smth is not null
GROUP BY u.`id`, u.username
HAVING u.`smth` IS NOT NULL 

这清楚地表明您希望每行都有一个单独的用户名,并且您不希望smth为NULL。在性能方面,所有这个版本都相当于你的第二个版本,而且这三个版本应该完全相同。