【问题标题】:SQL JOIN on foreign key that is not equal to primary key不等于主键的外键上的 SQL JOIN
【发布时间】:2019-01-10 23:19:27
【问题描述】:

我不完全知道如何正确表达这个问题,但我完全糊涂了。我们有一个测试考试,其中一个问题是:

按照演员拥有的电影数量降序排列 出现在。只显示名字、姓氏和数量 他们演过的动作片。(注:不幸的是所有演员 出现在动作片中的都出现在同一个 金额)。

正确答案显示如下:

SELECT 
    Actor.FirstName, Actor.LastName, COUNT(*)
FROM 
    Category 
JOIN 
    Film_Category ON Category.CategoryId = Film_Category.CategoryId
JOIN 
    Film on Film.FilmId = Film_Category.CategoryId
JOIN 
    Film_Actor on Film_Actor.FilmId = Film.FilmId
JOIN 
    Actor ON Actor.ActorId = Film_Actor.ActorId
WHERE 
    Category.Name = 'Action'
GROUP BY 
    Actor.FirstName, Actor.LastName
ORDER BY 
    COUNT(*) DESC

此查询返回:

JOHNNY  CAGE    64
ROCK    DUKAKIS 64
CHRISTIAN   GABLE   64
PENELOPE    GUINESS 64
MARY    KEITEL  64
OPRAH   KILMER  64
WARREN  NOLTE   64
SANDRA  PECK    64
MENA    TEMPLE  64
LUCILLE TRACY   64

让我感到困惑的是第二个 JOIN:

JOIN Film on Film.FilmId = Film_Category.CategoryId

比较Film.FilmIdFilm_Category.CategoryId 的作用是什么,因为它不是该表的外键?我什至怀疑答案是否正确,因为当我输入查询时:

SELECT 
    COUNT(Category.Name), Category.Name 
FROM 
    Film_Category 
INNER JOIN 
    Category ON Category.CategoryId = Film_Category.CategoryId 
GROUP BY 
    Category.Name 
ORDER BY 
    COUNT(Category.Name);

我明白了:

64  Action
66  Animation
68  Documentary

那么,大概所有演员都出现在所有动作片中?谁能帮帮我,因为我很快就要考试了,我迷路了!

【问题讨论】:

  • FK 和其他约束不需要查询。 (它们的存在仅仅意味着某些表达式返回正确的结果,否则不会。)重要的是表的含义,即表中的行表示什么。但常识表明,您不希望由具有等于类别 id 的电影 id 的行组成的行。 PS 规范要求按演员出演的电影数量进行排序。但代码按演员出演的动作片数量进行排序。
  • 这是输入表值的正确结果值吗?请给minimal reproducible example。 (这将涉及每人少于 66 部动作电影的示例数据。因为它将涉及您和我们可以轻松推理和检查的数据。)(并且代码不应仅仅因为它们是不相关的表而涉及在 ERD 中。)(并且 ERD 不应涉及与代码无关的表格。) PS 将文本包含为文本,而不是图像/链接。图片应该只为文本提供便利或提供文本不能提供的内容,而不是替换它。使您的帖子自成一体。 (给定 DDL,ERD 通常是多余的。)
  • PS 如果两个演员可以有相同的名字,那么这个查询也是错误的。还缺少许多适当的 PK/UNIQUE 声明。 (为什么您认为该查询应该是正确的?) PS 一个明智的限制是 Film.FilmId = Film_Category.FilmId`--但正如 Gordon Linoff 所说,Film 是“不需要”的,并且在这个查询中,与它的内部连接是错误 - 为每个演员及其每部电影及其每个类别返回一行,而这些行中动作片的每位演员的计数不是您想要的。
  • @philipxy 抱歉回复晚了,奇怪的是我没有收到任何通知。回想起来,这对我来说也没有任何意义,但我只是在学习,我的教授提供了这个答案,因此这让我很困惑。感谢您的回复,阅读所有答案,您的回复比我老师提供的答案给了我更多的视角,很遗憾。

标签: sql join foreign-keys sql-server-2017


【解决方案1】:

查询不正确。根据ER图,应该是:

SELECT a.FirstName, a.LastName, COUNT(*)
FROM Category c JOIN
     Film_Category fc
     ON c.CategoryId = fc.CategoryId JOIN
     Film_Actor fa
     ON fa.FilmId = fc.FilmId JOIn
     Actor a
     ON a.ActorId = fa.ActorId
WHERE c.Name = 'Action'
GROUP BY a.FirstName, a.LastName
ORDER BY COUNT(*) DESC;

请注意,不需要Film 表。也就是说,我认为这个问题的答案是:

SELECT a.FirstName, a.LastName,
       SUM(CASE WHEN c.Name = 'Action' THEN 1 ELSE 0 END) as num_action
FROM Category c JOIN
     Film_Category fc
     ON c.CategoryId = fc.CategoryId JOIN
     Film_Actor fa
     ON fa.FilmId = fc.FilmId JOIn
     Actor a
     ON a.ActorId = fa.ActorId
GROUP BY a.FirstName, a.LastName
ORDER BY COUNT(*) DESC;

问题是按所有部电影排序,但只显示动作电影的数量。

【讨论】:

  • 非常感谢!对于迟到的回复,我深表歉意,通常我会收到提供答案的通知,但我没有收到任何奇怪的消息。该查询是我的教授提供的,但它给我带来了很多困惑,感谢您解决这个问题。
【解决方案2】:

让我们检查一下'JOHNNY CAGE'

SELECT Actor.FirstName, Actor.LastName, COUNT(*) As AllPlayed
        FROM Film
        JOIN Film_Actor on Film_Actor.FilmId = Film.FilmId
        JOIN Actor ON Actor.ActorId = Film_Actor.ActorId
    Where FirstName ='JOHNNY' And LastName = 'CAGE'
    GROUP BY Actor.FirstName, Actor.LastName

结果:JOHNNY CAGE 29

强尼参演了 29 部电影,也没有参演 64 部动作片

那你的查询错了,换个试试

JOIN Film on Film.FilmId = Film_Category.CategoryId

JOIN Film on Film.FilmId = Film_Category.FilmId

....

SELECT Actor.FirstName, Actor.LastName, COUNT(*)
FROM Category JOIN Film_Category ON Category.CategoryId = Film_Category.CategoryId
              JOIN Film on Film.FilmId = Film_Category.FilmId
              JOIN Film_Actor on Film_Actor.FilmId = Film.FilmId
              JOIN Actor ON Actor.ActorId = Film_Actor.ActorId
WHERE Category.Name = 'Action'
GROUP BY Actor.FirstName, Actor.LastName
ORDER BY COUNT(*) DESC

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-05
    • 2020-07-07
    • 2020-12-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-16
    • 1970-01-01
    • 2021-01-20
    相关资源
    最近更新 更多