SQL - 选择一个元素出现两次的行

时间:2014-10-30 00:14:14

标签: mysql sql database

我正在完成一项任务,我需要找一些由导演执导的电影,这些电影导演多部影片由安吉丽娜朱莉主演。目前,我有这个:

SELECT DISTINCT t.title, n.name
FROM (
SELECT DISTINCT t.id theMovies
FROM name n
INNER JOIN cast_info c
ON (c.person_id = n.id)
INNER JOIN title t
ON (t.id = c.movie_id)
WHERE n.name = 'Jolie, Angelina'
) as newTable
INNER JOIN title t
ON (t.id = theMovies)
INNER JOIN cast_info c
ON (c.movie_id = t.id)
INNER JOIN name n
ON (n.id = c.person_id)
CROSS JOIN role_type
WHERE role = 'director';

此查询目前所做的是查找由Angelina Jolie主演的电影列表,然后列出这些电影的导演。我现在需要做的就是只保留导演所在的行至少另一行。有小费吗? 作为参考,这是我正在使用的数据库的图表: http://i.imgur.com/kj8qVgF.png 我对SQL也很陌生,所以任何改进我的查询的建议都会非常感激!

2 个答案:

答案 0 :(得分:2)

我会将其分解为几个部分并构建到您的最终查询。如果你是新手 SQL,将事物分解成一些东西并将它们重新组合在一起是一种很好的做法。有了这个,我将重申一下目标:找一些由安吉丽娜·朱莉导演电影的导演导演的电影。

我首先要拍摄安吉丽娜朱莉的所有电影:

SELECT t.id
FROM name n
JOIN cast_info c ON c.person_id = n.id
JOIN title t ON t.id = c.movie_id
WHERE n.name = 'Jolie, Angelina';

现在,让我们来看看这些电影的导演:

SELECT c.person_id
FROM cast_info c
JOIN title t ON t.id = c.movie_id
JOIN role_type r ON r.id = c.role_id
WHERE r.role = 'director' AND t.id IN(SELECT t.id
                                      FROM name n
                                      JOIN cast_info c ON c.person_id = n.id
                                      JOIN title t ON t.id = c.movie_id
                                      WHERE n.name = 'Jolie, Angelina');

我们可以将上述查询修改为按person_id分组,其计数(*)大于一(表示多部电影)。

SELECT c.person_id
FROM cast_info c
JOIN title t ON t.id = c.movie_id
JOIN role_type r ON r.id = c.role_id
WHERE r.role = 'director' AND t.id IN(SELECT t.id
                                      FROM name n
                                      JOIN cast_info c ON c.person_id = n.id
                                      JOIN title t ON t.id = c.movie_id
                                      WHERE n.name = 'Jolie, Angelina')
GROUP BY person_id
HAVING COUNT(*) > 1;

现在,我们需要查找这些导演指导的电影,并进行过滤,以便我们不会包含安吉丽娜朱莉的电影。

SELECT t.id
FROM title t
JOIN cast_info c ON c.movie_id = t.id
JOIN role_type r ON r.id = c.role_id
WHERE r.role = 'director' 
   AND c.person_id IN (SELECT c.person_id
                       FROM cast_info c
                       JOIN title t ON t.id = c.movie_id
                       JOIN role_type r ON r.id = c.role_id
                       WHERE r.role = 'director' AND t.id IN(SELECT t.id
                                                             FROM name n
                                                             JOIN cast_info c ON c.person_id = n.id
                                                             JOIN title t ON t.id = c.movie_id
                                                             WHERE n.name = 'Jolie, Angelina')
                       GROUP BY person_id
                       HAVING COUNT(*) > 1)
   AND t.id NOT IN(SELECT t.id
                   FROM name n
                   JOIN cast_info c ON c.person_id = n.id
                   JOIN title t ON t.id = c.movie_id
                   WHERE n.name = 'Jolie, Angelina');

我无法通过SQL Fiddle进行测试,因为它目前无法正常工作,但我会尽快这样做。有些东西可能需要调整,但请告诉我这是否有帮助。

答案 1 :(得分:0)

请尝试:

SELECT
      t.title
    , n.name
FROM title t
      INNER JOIN cast_info c
                  ON t.id = c.movie_id
      INNER JOIN name n
                  ON c.person_id = n.id
      INNER JOIN role_type r
                  ON c.person_role_id = r.id
      INNER JOIN (
                  SELECT
                        c.person_id
                      , r.id
                  FROM cast_info c
                        INNER JOIN role_type r
                                    ON c.person_role_id = r.id
                  WHERE r.role = 'director'
                        AND c.movie_id IN (
                              SELECT DISTINCT
                                    c.movie_id
                              FROM name n
                                    INNER JOIN cast_info c
                                                ON c.person_id = n.id
                              WHERE n.name = 'Jolie, Angelina'
                        )
                  GROUP BY
                        c.person_id
                      , r.id
                  HAVING COUNT(*) > 1
            ) d
                  ON c.person_id = d.person_id
                        AND r.id = d.id
;

尝试多部分查询"部分"如果它似乎不起作用,这有助于确定它可能失败的地方

-- 1
SELECT DISTINCT
    c.movie_id
FROM name n
    INNER JOIN cast_info c
                ON c.person_id = n.id
WHERE n.name = 'Jolie, Angelina'
;

-- 2
SELECT
    c.person_id
  , r.id
FROM cast_info c
    INNER JOIN role_type r
                ON c.person_role_id = r.id
WHERE r.role = 'director'
GROUP BY
    c.person_id
  , r.id
HAVING COUNT(*) > 1
;

-- 3
SELECT
    c.person_id
  , r.id
FROM cast_info c
    INNER JOIN role_type r
                ON c.person_role_id = r.id
WHERE r.role = 'director'
    AND c.movie_id IN (
          SELECT DISTINCT
                c.movie_id
          FROM name n
                INNER JOIN cast_info c
                            ON c.person_id = n.id
          WHERE n.name = 'Jolie, Angelina'
    )
GROUP BY
    c.person_id
  , r.id
HAVING COUNT(*) > 1
;