【问题标题】:How to get the count of a particular category for each year?如何获得每年特定类别的计数?
【发布时间】:2019-10-04 09:17:33
【问题描述】:

我正在尝试一个问题,要求我找到“对于每一年,计算那一年只有女性演员的电影数量”。

表架构如下:

--------------------   -----------------------   ----------------------
|   Movie          |   |     Person           |  |       Cast         |
--------------------   ------------------------  ----------------------
| MovieID  | year  |   |  PersonID  | Gender  |  | MovieID | PersonID |
--------------------   ------------------------  ----------------------

运行以下查询:

SELECT M.YEAR, COUNT(M.MID) NUMBER_OF_FEMALE_ONLY_MOVIES FROM MOVIE M 
WHERE M.MID IN (SELECT X.MID FROM (SELECT AX.MID, COUNT(AX.PID) TOTAL_CAST 
FROM M_CAST AX GROUP BY AX.MID) X 
WHERE 
X.TOTAL_CAST = (SELECT COUNT(A.PID) FROM M_CAST A, PERSON B WHERE A.MID = 
X.MID AND
TRIM(B.PID) = TRIM(A.PID) AND B.GENDER = 'Female')) GROUP BY M.YEAR

我的结果是:

---------------------------------------
| year | NUMBER_OF_FEMALE_ONLY_MOVIES  |
---------------------------------------
| 1999 |    1                          |
| 2005 |    1                          | 
| 2009 |    1                          |
| 2012 |    1                          |
| 2018 |    1                          |
----------------------------------------

但是对于没有任何此类电影的年份,我需要返回 0 作为计数。 例如。

2013 0

【问题讨论】:

    标签: sql mysql-python


    【解决方案1】:
        WITH 
    PERSON_CAST_MERGE AS
       (
        SELECT P.PID,C.MID,GENDER
        FROM PERSON P
        INNER JOIN M_CAST C ON C.PID = P.PID
       ),
        MALE_COUNT AS
       (
        SELECT F.MID FROM PERSON_CAST_MERGE F
        WHERE TRIM(F.GENDER) NOT  LIKE "%FEMALE%"
       ),
    FEMALE_COUNT AS
       (
        SELECT F.MID FROM PERSON_CAST_MERGE F
        WHERE TRIM(F.GENDER) LIKE "%FEMALE%"
       ),
     ONLY_FEMALE AS
     (
        SELECT F.MID FROM FEMALE_COUNT F
        WHERE F.MID NOT IN (SELECT M.MID FROM MALE_COUNT M)
     ),
     TEST AS
     (
     SELECT M.YEAR,COUNT(M.MID) AS NO_OF_MOVIES
     FROM ONLY_FEMALE F
    INNER JOIN MOVIE M ON M.MID = F.MID
    GROUP BY M.YEAR
     )
    
     SELECT M.YEAR,
     CASE  
        WHEN M.YEAR IN (SELECT F.YEAR FROM TEST F) THEN
            (SELECT F.NO_OF_MOVIES FROM TEST F WHERE F.YEAR = M.YEAR)
        WHEN M.YEAR <> (SELECT F.YEAR FROM TEST F) THEN
            0
     END
     AS NO_OF_MOVIES
     FROM MOVIE M
     GROUP BY M.YEAR
    

    【讨论】:

      【解决方案2】:

      我建议探索 CTE 中的数据以获得更好的理解。

      第一个 CTE (all_cast):返回整个电影演员表

      第二个 CTE (male_present):从存在男演员的 all_cast 返回电影 ID。

      结果:从 all_cast 返回电影,其中电影 ID 在 male_present 中不存在

      WITH all_cast AS (
          SELECT SUBSTR(m."year",-4) as 'Year', m.title, trim(m.MID) as MID, p.Name, trim(p.Gender) as Gender  
          FROM Movie m
          JOIN M_Cast mc 
              ON m.MID = mc.MID
          JOIN Person p 
              ON trim(mc.PID) = p.PID
      ),
      
      male_present AS (
          SELECT year, mid, name
          FROM all_cast
          WHERE Gender = 'Male'
      )
      
      
      SELECT year, COUNT(DISTINCT mid) as 'All Female Cast'
      FROM all_cast a
      WHERE NOT EXISTS (SELECT * FROM male_present WHERE a.mid = mid)
      GROUP BY year
      

      【讨论】:

        【解决方案3】:

        您只需要 group by with 子查询,因为您需要参考性别为女性的 personids 的 movieids

             SELECT YEAR, COUNT(*) FROM 
             MOVIE 
            Where MovieId IN (SELECT MOVIEId 
           from CAST WHERE PERSONID IN 
           (Select PersonId from Person Where 
            Gender ='FEMALE'))
            Group by Year 
        

        【讨论】:

          【解决方案4】:

          试试这个 - 一个 DISTINCT MovieID 是必需的,因为一部电影可能有多个女性演员。 Distinct 将提供电影的实际数量。

          SELECT 
          M.Year,
          COUNT(DISTINCT MovieID)  
          FROM Movie M
          INNER JOIN Cast C ON M.MovieID = C.MovieID
          INNER JOIN Person P ON C.PersonID = P.PersonID 
          WHERE P.Gender = 'Female'
          GROUP BY M.Year;
          

          【讨论】:

            【解决方案5】:

            我认为这个问题可以通过加入所有表和过滤女演员的 WHERE 子句来解决。在这种情况下,连接表也将提供更好的性能,而不是子查询。

            请尝试以下代码:

            Select year, count(*) 
            from movie 
            join Cast on movie.movieid = cast.movieid
            join person on person.personid = cast.personid
            where person.gender = 'Female'
            group by year
            

            请让我知道这是否适合您。

            【讨论】:

            • @marc_s 该方法不是为仅女性演员提供所需的结果,而是为至少一名女性演员提供结果
            【解决方案6】:

            通过使用外部左连接将您的查询与电影表合并,您可以获得所需的结果。与@Lucky 发布的答案相比,所花费的时间会非常短

            WITH FEMALE_ONLY AS
              (SELECT M.YEAR,
                      COUNT(M.MID) COUNT_ALL_FEMALE
               FROM MOVIE M
               WHERE M.MID IN
                   (SELECT Q.MID
                    FROM
                      (SELECT MC.MID,
                              COUNT(MC.PID) total
                       FROM M_CAST MC
                       GROUP BY MC.MID) Q
                    WHERE Q.total =
                        (SELECT COUNT(A.PID)
                         FROM M_CAST A,
                              PERSON B
                         WHERE A.MID = Q.MID
                           AND TRIM(B.PID) = TRIM(A.PID)
                           AND B.Gender = 'Female'))
               GROUP BY M.YEAR)
            SELECT DISTINCT M.year,
                            coalesce(FO.COUNT_ALL_FEMALE, 0) FEMALE_ONLY_MOVIES
            FROM Movie M
            LEFT OUTER JOIN FEMALE_ONLY FO ON M.year = FO.year
            ORDER BY M.year;
            

            【讨论】:

              【解决方案7】:

              你可以这样做

              select z.year, count(*)
              from Movie z
              where not exists (select *
                                from Person x, M_Cast xy
                                where x.PID = xy.PID and xy.MID = z.MID and x.gender!='Female')
              group by z.year;
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2015-05-17
                • 1970-01-01
                • 1970-01-01
                • 2013-01-09
                • 2015-11-14
                • 1970-01-01
                • 2021-04-13
                相关资源
                最近更新 更多