我是一个MySQL查询noobie所以我确信这是一个明显答案的问题。
但是,我正在研究这两个问题。他们会返回不同的结果集吗?我理解排序过程会以不同的方式开始,但我相信它们会返回相同的结果,第一个查询的效率稍高一些吗?
查询1:HAVING,然后是AND
SELECT user_id
FROM forum_posts
GROUP BY user_id
HAVING COUNT(id) >= 100
AND user_id NOT IN (SELECT user_id FROM banned_users)
查询2:WHERE,然后HAVING
SELECT user_id
FROM forum_posts
WHERE user_id NOT IN(SELECT user_id FROM banned_users)
GROUP BY user_id
HAVING COUNT(id) >= 100
答案 0 :(得分:2)
实际上,第一个查询的效率会降低(HAVING
之后应用WHERE
)
的更新强>
一些伪代码,用于说明查询的执行方式([非常]简化版本)
第一个问题:
1. SELECT user_id FROM forum_posts
2. SELECT user_id FROM banned_user
3.团体,计数等。
4.如果第一个结果集中的记录显示在第二个
第二次查询
1. SELECT user_id FROM forum_posts
2. SELECT user_id FROM banned_user
3.如果第一个结果集中的记录显示在第二个结果集中,则将其排除
4.分组,计数等。
步骤1,2的顺序并不重要,mysql可以选择它认为更好的任何东西。重要的区别在于步骤3,4。在GROUP BY
之后应用。分组通常比加入更昂贵(在这种情况下不包括记录可以考虑作为连接操作),因此分组记录越少,性能就越好。
答案 1 :(得分:0)
HAVING条件应用于按分组结果,并且由于您按user_id分组,因此所有可能的值都将出现在分组结果中,因此放置user_id条件并不重要
答案 2 :(得分:0)
对我来说,第二个查询更有效率,因为它会降低GROUP BY和HAVING的记录数。
或者,您可以尝试以下查询以避免使用IN:
SELECT `fp`.`user_id`
FROM `forum_posts` `fp`
LEFT JOIN `banned_users` `bu` ON `fp`.`user_id` = `bu`.`user_id`
WHERE `bu`.`user_id` IS NULL
GROUP BY `fp`.`user_id`
HAVING COUNT(`fp`.`id`) >= 100
希望这有帮助。
答案 3 :(得分:0)
您已经回答两个查询将显示相同的结果以及各种更有效的意见。
我的意见是,效率差异(速度),只有优化器才会产生不同的计划 2查询。我认为对于最新的MySQL版本,优化器足够聪明,可以为任一查询找到相同的计划,因此根本没有区别但是当然可以测试并查看EXPLAIN的执行计划或针对某些测试表运行2个查询。
我会在任何情况下使用第二个版本,只是为了安全起见。
让我补充一点:
COUNT(*)
通常比MySQL中的COUNT(notNullableField)
更有效。在未来的MySQL版本中修复之前,请在适用的地方使用COUNT(*)
。因此,您也可以使用:
SELECT user_id
FROM forum_posts
WHERE user_id NOT IN
( SELECT user_id FROM banned_users )
GROUP BY user_id
HAVING COUNT(*) >= 100
NOT IN
之前,还有其他方法可以实现相同(到GROUP BY
)子结果。使用LEFT JOIN / NULL
:
SELECT fp.user_id
FROM forum_posts AS fp
LEFT JOIN banned_users AS bu
ON bu.user_id = fp.user_id
WHERE bu.user_id IS NULL
GROUP BY fp.user_id
HAVING COUNT(*) >= 100
使用NOT EXISTS
:
SELECT fp.user_id
FROM forum_posts AS fp
WHERE NOT EXISTS
( SELECT *
FROM banned_users AS bu
WHERE bu.user_id = fp.user_id
)
GROUP BY fp.user_id
HAVING COUNT(*) >= 100
3种方法中哪一种更快取决于您的表格大小和许多其他因素,因此最好使用您的数据进行测试。
答案 4 :(得分:-1)
不,它没有给出相同的结果。
因为第一个查询将从count(id)条件
中过滤记录另一个查询过滤器记录然后应用having子句。
正确编写第二个查询