【问题标题】:Grouped JOIN query in MySQL - using the ON vs. HAVING condition for filtering (any difference?)MySQL 中的分组 JOIN 查询 - 使用 ON 与 HAVING 条件进行过滤(有什么区别吗?)
【发布时间】:2012-09-15 12:20:26
【问题描述】:

以下是伪查询,所以我不关心结果,但是以下 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`

【问题讨论】:

  • 这很难说(也许是无关紧要的),因为您的查询并没有真正的意义。您返回的列在 GROUP BY 查询中既不聚合也不分组。
  • 为什么不在WHERE 子句中设置u.`smth` 的条件?
  • @GiantofaLannister 聚合将使其成为不可能。
  • 在查询上运行 explain 看看 mysql 说了什么。
  • @KeithRandall 没有任何区别。

标签: mysql join filtering


【解决方案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。在性能方面,这个版本都和你的第二个版本相当,三个应该差不多。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 感谢您的澄清。很有道理。
    猜你喜欢
    • 2018-09-20
    • 2010-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多