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;

このクエリは、特定の年にその賞を授与したすべての機関から 1 人の人物が指名されたすべての賞を検索するように設計されています。基本的には 1 人で、1 つの賞を与えた機関の数を数え、その値をその賞を与えた機関の最大数と比較します。

目的の出力は次のようになります。

"personname"    "award" "year"

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

これにより、私が望むセットが得られますが、別の方法で行う方が効率的かどうかはわかりません。EXISTS で動作させようとしましたが、うまくいきませんでした。

主な質問: このクエリを実行するためのより効率的な方法はありますか?

4

1 に答える 1

3

複雑なクエリの場合と同様に、TDQD (テスト駆動クエリ設計) を使用して問題を段階的に解決します。各段階を個別にテストし、結果を確認して、正しい答えにたどり着くことができます。

3 つのテーブルを示していることに注意してください。あなたのクエリはそれらのうちの2つを使用していますが、4番目のnominees. あなたは私たちにそのスキーマを提供し、特定の年に賞を提供するすべての機関から誰が賞を受賞したかを尋ねたので、それwinnersは と同じであると想定しています.nominees

ステージ 1: 1 年に特定の賞を授与した機関の数は?

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

ステージ 2: 1 年間に特定の賞を何回獲得しましたか?

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

ステージ 3: 2 つのカウントが同じ行?

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 に答える