不使用子查询SQL构造

时间:2013-05-02 16:03:56

标签: sql oracle

ACTOR (id, fname, lname, gender)
MOVIE (id, name, year, rank)
CASTS (pid, mid, role)
WHERE pid references ACTOR id
mid references Movie id

列出x没有y的电影(x和y是演员)。

我发现很难用NOT编译SQL。这是我的尝试。由于第二个演员没有出现,我无法完成它

SELECT m.name
FROM MOVIE m
WHERE m.id NOT IN (SELECT c.mid
                       FROM CASTS c, ACTOR a
                       WHERE c.pid = a.id AND a.name = "adam..") 

4 个答案:

答案 0 :(得分:4)

使用 NOT EXISTS

SELECT m.name                       -- Show the names                      
FROM movie m                        -- of all movies
WHERE EXISTS                        -- that there was
      ( SELECT *                    -- a role
        FROM casts c                -- casted to
          JOIN actor a              -- actor with
            ON c.pid = a.id
        WHERE c.mid = m.id  
          AND a.name = 'Actor X'    -- name X
      ) 
  AND NOT EXISTS                    -- and there was not
      ( SELECT *                    -- any role
        FROM casts c                -- casted
          JOIN actor a              -- to actor with
            ON c.pid = a.id
        WHERE c.mid = m.id 
          AND a.name = 'Actor Y'    -- name Y
      ) ;

您还可以使用 NOT IN 。请注意,如果NULLmovie.id列中有casts.mid行,则可能会给您带来意外结果:

SELECT m.name                       -- Show the names                      
FROM movie m                        -- of all movies
WHERE m.id IN                       -- but keep only the movies that
      ( SELECT c.mid                -- movies that
        FROM casts c                -- had a role casted to
          JOIN actor a              -- actor with
            ON c.pid = a.id
        WHERE a.name = 'Actor X'    -- name X
      ) 
  AND m.id NOT IN                   -- and not the movies
      ( SELECT c.mid                -- that
        FROM casts c                -- had a role casted
          JOIN actor a              -- to actor with
            ON c.pid = a.id
        WHERE a.name = 'Actor Y'    -- name Y
      ) ;

答案 1 :(得分:2)

您还可以使用经常被忽视的MINUS

SELECT Movie.id, Movie.name
  FROM Actor
  INNER JOIN Casts ON Actor.id = Casts.pid
  INNER JOIN Movie ON Casts.mid = Movie.id
  WHERE Actor.id = 1
MINUS SELECT Movie.id, Movie.name
  FROM Actor
  INNER JOIN Casts ON Actor.id = Casts.pid
  INNER JOIN Movie ON Casts.mid = Movie.id
  WHERE Actor.id = 2

上述查询中的WHERE Actor.id可以用其他方式替换,以唯一地标识actor,例如通过其名称。

答案 2 :(得分:1)

SELECT  a.*
FROM    Movie a
        INNER JOIN Casts b
            ON a.ID = b.mID
        INNER JOIN Actor c
            ON b.pid = c.ID
        LEFT JOIN
        (
            SELECT  aa.mid
            FROM    Casts aa
                    INNER JOIN Actor bb
                        ON aa.pid = bb.ID
            WHERE   bb.fName = 'Y_Name'
        ) d ON  a.id = d.mid
WHERE   c.fname = 'X_Name' AND
        d.mid IS NULL

在子查询上进行额外连接的原因是因为我们按照actor的名称过滤记录。


假设你有这些记录集

ACTOR

╔════╦════════╗
║ ID ║ FNAME  ║
╠════╬════════╣
║  1 ║ X_Name ║
║  2 ║ Y_Name ║
╚════╩════════╝

MOVIE

╔════╦══════╗
║ ID ║ NAME ║
╠════╬══════╣
║  1 ║ Mov1 ║
║  2 ║ Mov2 ║
║  3 ║ Mov3 ║
╚════╩══════╝

CAST

╔═════╦═════╗
║ PID ║ MID ║
╠═════╬═════╣
║   1 ║   1 ║ <<== EXPECTED OUTPUT since Y_NAME is not present
║   1 ║   2 ║                      on Movie Mov1
║   2 ║   2 ║
║   1 ║   3 ║
║   2 ║   3 ║
╚═════╩═════╝

输出

╔════╦══════╗
║ ID ║ NAME ║
╠════╬══════╣
║  1 ║ Mov1 ║
╚════╩══════╝

答案 3 :(得分:1)

首先获取Actor X的所有电影。然后检查过滤掉任何还包含Actor Y的电影。

SELECT m.name
FROM MOVIE m, CASTS c, ACTOR a
WHERE m.id = c.mid
    AND c.pid = a.id
    AND a.name = "ACTOR X"
    AND NOT EXISTS (
        SELECT 1
        FROM CASTS c1, ACTOR a1
        WHERE c1.pid = a1.id
            AND m.id = c1.mid
            AND a1.name = "ACTOR Y"
    )