这个mySQL查询是如何工作的?

时间:2015-05-26 16:28:44

标签: mysql

我试图了解mysql查询如何使用和不使用GROUP BY。

想象一下,我有一个FILM_ACTORS表,其中每个ACTOR_ID都有一个相应的FILM_ID。所以同一个演员参加了N部不同的电影。

我想选择参与20部电影的演员:

SELECT actor_id FROM film_actor GROUP BY actor_id HAVING COUNT(film_id) = 20;

此查询有效,并返回参与20部电影的actor_ids。 但是,如果我刚刚做了什么:

SELECT actor_id FROM film_actor HAVING COUNT(film_id) = 20;

为什么此查询仅返回值,如果我将其等于film_actor表(5463)的SIZE:

SELECT actor_id FROM film_actor HAVING COUNT(film_id) = 5463;

在这种情况下,它会返回actor_id = 1.为什么?是在不考虑相应的actor_ids的情况下选择film_ids吗?

3 个答案:

答案 0 :(得分:5)

GROUP BY将结果按以下列的值分组,通常与聚合函数一起使用(例如,COUNT)。

因此,您的第一个查询会为actor_id的每个值返回一行,而HAVING会将结果限制为计数为20的那些

如果没有GROUP BY子句,聚合函数将作用于所有行。因此,您的第二个查询是选择电影数量为20的actor_id,但如果没有分组,则计数为5463(即表格中的行数)。在这种情况下返回的actor_id未确定(即,可能是其中任何一个)。

答案 1 :(得分:4)

第二个查询中没有GROUP BY。在COUNT子句中使用聚合函数HAVING意味着查询最多将返回一行。

与此查询比较:

SELECT actor_id, COUNT(film_id) FROM film_actor

返回单个行,例如

actor_id  COUNT(film_id)
--------  --------------
      42            5463

(注意:默认情况下,MySQL将返回该查询的结果。其他数据库将拒绝该查询,并在"类型错误中引发"非聚合不在组中。问题在于引用到actor_id列表中的SELECT。要使该查询在其他数据库中工作,我们需要从SELECT列表中删除actor_id。我们可以让MySQL的行为方式相同,如果我们将sql_mode设置为包含ONLY_FULL_GROUP_BY。)

请注意,actor_id返回的值是来自"某行"的值。它不是确定性返回该值的哪一行,它可以来自任何行。 COUNT返回的值来自整个表格。

如果你想为每个演员提供COUNT,你需要一个GROUP BY子句,就像你的第一个查询一样。

    SELECT actor_id, COUNT(film_id) FROM film_actor GROUP BY actor_id

从该查询开始,您可以添加HAVING子句。您还可以从COUNT(film_id)列表中删除SELECT。但是,您无法移除GROUP BY,而不会影响COUNT(film_id)返回的内容。

答案 2 :(得分:3)

所以,假设你有:

+---------------------------------+
| actor_id | actor_name | film_id |
+---------------------------------+
|        4 |       John |       3 |
|        4 |       John |       4 |
|        5 |       Alex |       3 |
+---------------------------------+

当你跑步时:

SELECT actor_id, COUNT(film_id) AS Films FROM film_actor GROUP BY actor_id;

我们会得到:

+------------------+
| actor_id | Films |
+------------------+
|        4 |     2 |
|        5 |     1 |
+------------------+

所以,我们可以这样做:

SELECT actor_id, COUNT(film_id) AS Films FROM film_actor GROUP BY actor_id WHERE Films = 2;

这应该只返回4的actor_id。