Sql 如何获得每年特定类别的计数?

Sql 如何获得每年特定类别的计数?,sql,mysql-python,Sql,Mysql Python,我正在尝试一个问题,这个问题告诉我,每年都会发现,数一数那一年只有女性演员的电影数量 表模式如下所示: -------------------- ----------------------- ---------------------- | Movie | | Person | | Cast | -------------------- ------------------------ -----

我正在尝试一个问题,这个问题告诉我,每年都会发现,数一数那一年只有女性演员的电影数量

表模式如下所示:

--------------------   -----------------------   ----------------------
|   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作为没有任何此类电影的年份的计数。 例如


您只需要GROUPBY with子查询,因为您需要引用性别为女性的Personid的电影ID

     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 

我认为这个问题可以通过连接所有表并过滤女性演员的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

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

试试这个-需要一个不同的电影ID,因为一部电影可能有多个女性演员。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;

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

仅以女性作为 选择M.YEAR, COUNTM.MID COUNT所有女性 从电影M M.MID在哪里 选择Q.MID 从…起 选择MC.MID, COUNTMC.PID总计 来自M_CAST MC 由MC.midq分组 其中Q.total= 选择COUNTA.PID M_投了一个球, B人 其中A.MID=Q.MID 和TRIMB.PID=TRIMA.PID B.性别=‘女性’ 按M年分组 选择不同的M.year, coalesceFO.COUNT所有女性,0部女性电影 从电影M 左外连接内螺纹仅适用于M.year=FO.year 年订购;
我建议探索CTE内的数据,以便更好地理解

第一个CTE all_演员阵容:返回整个电影演员阵容

第二个CTE男演员出席:返回所有男演员的电影id

结果:从所有演员中返回电影,其中男性演员中没有电影id

你可以这样做

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;

@marc_s不是只为女性演员提供要求的结果,而是至少为一名女性演员提供结果
    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
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
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;