1

使用以下架构:

create table awards(
aid int primary key
, name varchar(100) not null );

create table institutions(
iid int primary key
, name varchar(100) not null );

create table winners(
aid int
, iid int
, year int
, filmname varchar(100)
, personname varchar(100)
, primary key (aid, iid, year)
, foreign key tid references awards(aid)
, foreign key cid references institutions(iid) );

我创建了以下查询:

SELECT nominees.personname as personname, awards.name as award, nominees.year as year 

FROM nominees, institutions, awards WHERE institutions.iid = nominees.iid and 
awards.aid = nominees.aid and personname is not null 

GROUP BY nominees.personname, awards.name, nominees.year 

HAVING ((awards.name, count(DISTINCT institutions.name)) in 
(SELECT awards.name as 
awards, count(DISTINCT institutions.name) 
FROM nominees, awards, institutions 
WHERE nominees.aid = awards.aid and nominees.iid = institutions.iid 
GROUP BY awards.name)) 

ORDER BY nominees.personname, awards.name;

此查询旨在查找在特定年份授予该奖项的每个机构都提名了一个人的所有奖项。它本质上需要一个人并计算授予他们单个奖项的机构数量,并将该值与授予该奖项的最大机构数量进行比较。

所需的输出应如下所示:

"personname"    "award" "year"

"Alexandre"     "score" "2011"
"Skyfall"       "song"  "2013"
"Tangled"       "song"  "2011"

这给出了我想要的集合,但是我不确定以不同的方式做它是否更有效。我试图让它与 EXISTS 一起工作,但我没有太多运气。

主要问题:有没有更有效的方法来做这个查询?

4

1 回答 1

3

像往常一样处理复杂查询,我使用 TDQD(测试驱动查询设计)分阶段解决问题。每个阶段都可以单独测试,并检查结果,确保您得到正确的答案。

我注意到您向我们展示了三张桌子;您的查询使用其中两个,但提到第四个,nominees. 我假设这winners与 相同nominees,因为您给了我们该架构并询问谁在给定年份从每个提供该奖项的机构中获得了该奖项。

第一阶段:一年有多少机构颁发了特定奖项?

SELECT aid, year, COUNT(*) AS num_awards
  FROM winners
 GROUP BY aid, year;

第 2 阶段:一个人一年获得了多少次特定奖项?

SELECT aid, year, personname, COUNT(*) AS num_person_awards
  FROM winners
 GROUP BY aid, year, personname;

第 3 阶段:两个计数相同的行?

SELECT n.aid, n.year, w.personname
  FROM (SELECT aid, year, COUNT(*) AS num_awards
          FROM winners
         GROUP BY aid, year
       ) AS n
  JOIN (SELECT aid, year, personname, COUNT(*) AS num_person_awards
          FROM winners
         GROUP BY aid, year, personname
       ) AS w
    ON n.aid = w.aid AND n.year = w.year AND n.num_awards = w.num_person_awards

第 4 阶段:将结果集中的奖项 ID 替换为奖项名称

SELECT a.name AS awardname, a.year, w.personname
  FROM (SELECT aid, year, COUNT(*) AS num_awards
          FROM winners
         GROUP BY aid, year
       ) AS n
  JOIN (SELECT aid, year, personname, COUNT(*) AS num_person_awards
          FROM winners
         GROUP BY aid, year, personname
       ) AS w
    ON n.aid = w.aid AND n.year = w.year AND n.num_awards = w.num_person_awards
  JOIN awards AS a
    ON a.aid = n.aid;

我没有尝试过这是否比您的查询更快,但它看起来更简单,所以我认为它有合理的机会更快地工作。


这就是我格式化您的查询的方式:

SELECT nominees.personname AS personname, awards.name AS award, nominees.year AS year
  FROM nominees
  JOIN institutions ON institutions.iid = nominees.iid
  JOIN awards ON awards.aid = nominees.aid
 WHERE personname IS NOT NULL 
 GROUP BY nominees.personname, awards.name, nominees.year 
HAVING (awards.name, COUNT(DISTINCT institutions.name) IN 
            (SELECT awards.name AS awards, COUNT(DISTINCT institutions.name) 
               FROM nominees, awards, institutions 
              WHERE nominees.aid = awards.aid and nominees.iid = institutions.iid 
              GROUP BY awards.name)
 ORDER BY nominees.personname, awards.name;
于 2013-03-06T06:39:36.453 回答