2

私は映画データベースでより多くのJOIN操作に取り組んでいます。私の質問は問題#16です:「アート・ガーファンクル」で働いたすべての人々をリストしてください

最初にArtGarfunkelが含まれるすべての映画を1つの値として取得し、次に同じ映画に含まれるすべての人の名前を最初の値と比較して取得する必要があります。

私は自分のクエリを思いついたのですが、ロジックでは動作するはずですが、タイムアウトが原因ではありません(非効率的なクエリが原因であると想定しています)

私の質問:

SELECT DISTINCT a.name
FROM actor a
JOIN casting b ON (a.id=b.actorid) 
JOIN movie c ON (b.movieid=c.id)
WHERE c.title IN(SELECT z.title
FROM movie z
JOIN casting y ON (z.id=y.movieid)
JOIN actor x on (y.actorid=x.id)
WHERE x.name='Art Garfunkel')

別のバージョン:

SELECT DISTINCT actor.name
FROM movie,actor,casting
WHERE movie.id=casting.movieid
AND actor.id=casting.actorid
AND movie.title IN(SELECT movie.title
FROM movie,actor,casting
WHERE movie.id=casting.movieid
AND actor.id=casting.actorid
AND actor.name='Art Garfunkel')

これらは両方とも、上記に示されているものをクエリしようとしてタイムアウトが発生したことを示す解析エラーをスローします。

回答として受け入れられた、彼らが提供したクエリのバージョンは次のとおりです。

SELECT DISTINCT d.name
FROM actor d JOIN casting a ON (a.actorid=d.id)
   JOIN casting b ON (a.movieid=b.movieid)
   JOIN actor c ON (b.actorid=c.id 
                AND c.name='Art Garfunkel')
  WHERE d.id!=c.id

私の論理はここで完全に間違っていますか?それとも、クエリが非常に非効率的であるということですか(私は考えています)。実行して正しい答えを得るように修正する方法はありますか?それとも、正しいクエリが行う方法をより論理的に考える必要がありますか?

非常に多くの質問がありましたが、そのクエリが機能しなかった理由と次のステップについてのフィードバックが必要でした。

4

12 に答える 12

1

Here are the answers to all of the sql zoo questions: answers

SELECT a.name
 FROM casting c JOIN actor a ON
  a.id = c.actorid
 WHERE 
  a.name <> 'Art Garfunkel' AND
  c.movieid 
 IN (
  SELECT m.id
     FROM casting c JOIN movie m ON
       m.id = c.movieid
     JOIN actor a ON
       c.actorid = a.id
     WHERE a.name = 'ART Garfunkel'
)
ORDER BY a.name
于 2013-03-17T22:33:08.180 に答える
0
SELECT a.name FROM actor a 
    JOIN casting c ON a.id=c.actorid 
    JOIN movie m ON c.movieid=m.id
    WHERE c.movieid IN 
        (SELECT movieid FROM casting WHERE actorid IN
            (SELECT id FROM actor WHERE name = 'Art Garfunkel')) 
    AND a.name <> 'Art Garfunkel'
于 2016-07-25T15:05:38.127 に答える
0

さて、提案された解決策は一見しただけでは意味を成さないため (Number-16)、実際にこれを理解するのに数時間かかりました。しかし、私は自分の解決策を思いついた後、なんとかそれを理解することができました。最初に私の解決策:

select name from actor 
join casting on actor.id=actorid
where movieid in
(select movieid from casting
join actor on actorid=actor.id
where name='Art Garfunkel')
and name <>'Art Garfunkel'

Art Garfunkel が役割を持っていた movieid のすべてのactorid (= 外部選択) を検索し (内部選択)、Art Garfunkel 自身を除外します。

十分に単純です。

クエリの最後に次の行を追加できます。

order by name

しかし、クエリはもはや正しいものとして受け入れられません。

他の人の解決策を理解できないとイライラするので、他の場所で与えられた解決策に時間を費やしました。ここに再びあります:

SELECT DISTINCT a.name
FROM actor a 
JOIN casting b ON (a.id=b.actorid)
JOIN casting c on b.movieid=c.movieid
JOIN actor d ON (c.actorid=d.id 
                AND d.name='Art Garfunkel')
WHERE a.id!=d.id

興味深いことに、これを少し異なる方法で記述し、最後の結合から where 句を取り出すことができます。

SELECT DISTINCT a.name
FROM actor a 
JOIN casting b ON (a.id=b.actorid)
JOIN casting c on b.movieid=c.movieid
JOIN actor d ON (c.actorid=d.id)
WHERE d.name='Art Garfunkel' 
AND a.id!=d.id

いずれにせよ、このクエリを後方に見る必要があります。そうしないと意味がありません。これは何が起こるようです:

actor-d (または、最初に評価されると思われる Where 句の最初の部分) が Art Garfunkel を設定 (または制限) し、これをcast-cに戻します。 cast -cは Art Garfunkel から movieid を検索し (ちなみに、これは 2 つあります。catch-22 の 1412 と Boxing Helena の 1597 です)、これらを cast-b のフィルターとして設定ますその後、 Casting-bは、Garfunkel からのこれら 2 つの映画にフィルターを設定して、 actor-aのすべてのアクター ID に戻り、これら 2 つの映画に出演したすべての俳優の名前が検索されます。最後に、アート ガーファンクルが除外されます。

私には、これが何かの機械語であるかのように感じられます。分別のある人間なら、このような考え方はしないでしょう (少なくとも私はそうは思いません)。

于 2014-10-25T18:07:08.200 に答える
0

この質問はジュリー・アンドリュースの項目 (現在sqlzooの #13 ) に似ていると思ったので、基本的にビル・カーウィンのエレガントなソリューションをジュリー・アンドリュースの問題に適応させて、明らかにエレガントではない方法でこの問題を解決しました。このソリューションはJOINs、この一連の演習のポイントと思われるすべてを使用します。本質的に、私がこれを概念化した方法は、アート・ガーファンクルが他の人もキャスティングされた映画にキャスティングされたということです。つまり、ガーファンクル<->出演<->映画<->出演<->共演者名。

私は非常に新しいSQLユーザーです(正直なところ、24時間未満)ので、これは扱いにくいかもしれませんが、うまくいきました:

SELECT a2.name
FROM actor a1
JOIN casting AS c1 ON (a1.id = c1.actorid)
JOIN movie ON (c1.movieid=movie.id)
JOIN casting AS c2 ON (movie.id=c2.movieid)
JOIN actor AS a2 ON (c2.actorid=a2.id)
WHERE
    a1.name='Art Garfunkel'
    AND a2.name <> 'Art Garfunkel'
GROUP BY a2.name
于 2016-02-28T07:28:47.887 に答える
0

上記の SQL の回答は次のとおりです。

SELECT a.name from actor a 
inner join casting c on a.id=c.actorid 
inner join movie m on m.id=c.movieid 
WHERE m.id in (SELECT c.movieid from casting c inner join actor a 
on a.id=c.actorid WHERE a.name='Art Garfunkel') 
and a.name<>'Art Garfunkel'

ただし、まだ共用体に慣れている SQL の初心者として、最初に思いついたコードは次のとおりです。

SELECT name from actor WHERE id IN 
(SELECT actorid from casting WHERE movieid IN (SELECT movieid 
from casting WHERE actorid IN (SELECT 
id from actor WHERE name='Art Garfunkel'))) 
and name<>'Art Garfunkel'

基本的には上記の説明と同じことを行います。SELECT idステートメントは Art のアクター ID を見つけます。SELECT movieidは、彼が出演した映画を検索します。SELECT actoridは、それらの映画の他の俳優を検索し、 SELECT nameは、その名前を検索します。

ユニオンのやり方を学ぶことは理想的で、最終的には内部結合構文にたどり着きましたが、SELECT に慣れているか、まだユニオンについて学んでいる SQL ユーザーのために、別の答えを投げかけます。

于 2015-05-13T00:33:35.917 に答える
0

機能する別のソリューションは次のとおりです。

SELECT name
FROM casting
JOIN actor ON actor.id=actorid
WHERE movieid IN (SELECT movieid FROM casting WHERE actorid = 
   (SELECT id FROM actor WHERE name='Art Garfunkel'))
GROUP BY actorid
HAVING name<>'Art Garfunkel'
于 2015-10-12T09:52:47.360 に答える