什么是检索以下结果集的最佳SQL查询

时间:2011-11-01 22:11:33

标签: sql optimization

我会提前说,并且出于对时间和网站的尊重 - 这 是一项家庭作业。 然而,我已经想到了并编写了一个解决方案,但由于我无法成功剖析或获得相关的第三方意见,我感到有点恼火其他地方是否实际上是一个好的。

说我有一个简单的电影参与信息表(人物,电影,人物与电影的关系)如下:

create table film
(
    person_name varchar(48) not null,
    film_title varchar(128) not null,
    relation varchar(48) not null
);

-- { 'Mel Gibson', 'Braveheart', 'director' }
-- { 'Mel Gibson', 'Braveheart', 'cast' }
-- { 'Steven Spielberg', 'A.I.' , 'director' }
-- { 'Hilary Swank', 'Million Dollar Baby', 'cast' }
-- etc

数据库和表格不是由我创建或维护的,我只是从中查询信息。

我需要为他们指导的每部电影中的演员(在镜头前行动)制作一组人名。对于那些导演至少一部他们没有采取行动的电影的人,或那些没有指挥任何事情的人,这种情况应该

我的查询(据我所知,可以证明产生正确的结果集),瞧瞧:

(   
    select  person_name 
    from    film 
    where   relation = 'director'
)
except 
(
    select person_name
    from 
    (   
        (
            select  person_name, film_title 
            from    film 
            where   relation = 'director'
        ) 
        except 
        (   
            select  person_name, film_title 
            from    film 
            where   relation = 'cast'
        )
    ) as director_behind_camera_for_film
)

我想知道查询是否合理,或者我是否一直在想这个问题?如果是后者,请您提供更好的解决方案或解释?

不要太注意我在任何地方都使用字符串的事实(代理键可能已经被用过了) - 这是一个简化的例子,但它仍然证明了我的挑战。

3 个答案:

答案 0 :(得分:4)

SELECT tmp.person_name FROM
(
   SELECT person_name, film_title, COUNT(relationship) as cnt
   FROM film
   WHERE relationship IN ('cast', 'director')
   GROUP BY person_name, film_title
) as tmp
GROUP BY person_name
HAVING SUM(cnt) = COUNT(cnt)*2

SELECT tmp.person_name FROM
(
   SELECT person_name, film_title, COUNT(DISTINCT(relationship)) as cnt
   FROM film
   WHERE relationship IN ('cast', 'director')
   GROUP BY person_name, film_title
) as tmp
GROUP BY person_name
HAVING SUM(cnt) = COUNT(cnt)*2

答案 1 :(得分:3)

“我需要为他们所导演的每部电影中的导演(在镜头前行动)制作一套人名。因此,对于导演至少一部电影的人来说,条件不适用他们没有采取行动,或者没有指挥任何事情的人。“

你的短语的后半部分(“或者没有指示任何东西的人”)不正确。

如果一个人X没有指示任何东西,那么X指导的一组电影是空集,并且可能已经向你解释了(如果没有,那么我现在正在做)通用量化(已经在ALL ...中投射了空集总是产生“真”。

因此,如果X根本没有指向任何东西,那么X确实是在“他指导的所有电影”中投射的,因此,X应该包含在结果集中。 (如果这不是要求的方式,则要求应明确说明。)

那就是说,我在Can all SQL queries be represented in Relational Algebra, Domain and Tuple relational calculus中解释了关系师的运作细节(这是你获得结果所需要的)。

主题是不同的(经理和员工,而不是导演和电影),但查询的性质完全相同:让我得到与所有Y的Z关系的X.

修改

后来我意识到存在一个“微小的”差异:在这个特定的导演,演员和电影的例子中,“所有Y”的集合本身“依赖于”正在考虑的特定X.这是一个额外的复杂性,超出了关系鸿沟的更典型应用范围。解决这个问题可能需要使用GROUP()左右构建与关系值属性的关系,但我还没有弄清楚细节(并且GROUP()之类的运算符不太可能是你讲座的一部分。) / p>

向任何被引导忽视问题特定方面的人道歉。

答案 2 :(得分:1)

这看起来好像应该有效,而且更标准的SQL:

select director.person_name 
from film director 
full outer join film actor 
    on director.person_name = actor.Person_name
    and director.film_title= actor.film_title
where actor.relationship = 'cast'
and director.relationship = 'director'
and actor.person_name is not null
and director.person_name is not null