【问题标题】:Subquery to count items, and then group them by a field of the main query without duplicates子查询对项目进行计数,然后按主查询的字段将它们分组,不重复
【发布时间】:2019-12-31 14:52:55
【问题描述】:

我想统计一个“子”在 N..N 关系中出现的次数,并按“父”的字段对结果进行分组。


我很难说出确切的话,所以假设我有 3 张桌子:电影演员播放 ,其中 PlayMovieActor 之间的关系。演员可以出演电影。 可能有些演员存在于数据库中,但从未在数据库的任何电影中演出过。

电影表中,我有一个流派

我想统计每个流派的演员数量,而不是每个流派多次计算同一个演员。


我目前在每次播放的 actor_id 上使用 DISTINCT,这意味着理论上在同一部电影中多次播放的演员将出现一次......但这是一个没有意义的场景(因为该演员只会出现播放表中的每部电影一次),所以它是无用的,而不是我想要的。有更好的主意吗?

我想将所有内容保存在一个查询中,因为我实际上正在执行其他子查询来获取每个流派的其他统计信息。

这是我的查询的样子,没有其他子查询:

SELECT
    movie.genre,

    SUM(
        SELECT COUNT(DISTINCT play.actor_id)
        FROM play
        WHERE play.movie_id = movie.id
    ) AS number_of_actors

    FROM movie

    GROUP BY movie.genre

目前,如果一个演员演过几部电影,他会被计算几次。

【问题讨论】:

  • 电影可以没有演员吗?意思是,play 表中是否有电影id 没有对应的行?

标签: mysql count correlated-subquery distinct-values


【解决方案1】:

只需根据各自的关系在各个表之间做一个简单的INNER JOIN,并在一组genre 上使用COUNT(DISTINCT ..),以获得每个流派的独特演员:

SELECT 
  m.genre, 
  COUNT(DISTINCT p.actor_id) AS number_of_actors 
FROM movie AS m 
JOIN play AS p ON p.movie_id = m.id 
GROUP BY m.genre

【讨论】:

    【解决方案2】:

    您的问题是您无法在求和的每个元素之间进行不同的通信,因此您最终会重复值。将其写为JOIN 更简单。我使用了LEFT JOIN,以防电影在play 表中没有条目,在这种情况下COUNT 将为0。

    SELECT m.genre
           COALESCE(COUNT(DISTINCT p.actor_id), 0) AS number_of_actors
    FROM movie m
    LEFT JOIN play p ON p.movie_id = m.id
    GROUP BY m.genre
    

    【讨论】:

    • 我接受了这个答案而不是 Madhur Bhaiya 的答案,因为这个答案会列出每部电影,即使计数为零,但两个答案都有效,因为我没有提到这一点。谢谢!
    • @JoeyQuint 不用担心。我很高兴能帮上忙。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-01
    • 2014-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多