The JOIN operation/ja
Language: | English • 日本語 • 中文 |
---|
game ゲームテーブル 試合日や参加チームなどを記録 id 試合id mdate 試合日 stadium スタジアム team1 チーム1(アルファベット3文字) team2 チーム2(アルファベット3文字) goal ゴールテーブル ゴールの記録 matchid 試合id teamid チームid(アルファベット3文字) player プレイヤー gtime ゴール時間 eteam 参加チームテーブル id チームid(アルファベット3文字) teamname チーム名前 coach コーチ PK 主キー FK 外部キー
id | mdate | stadium | team1 | team2 |
---|---|---|---|---|
1001 | 8 June 2012 | National Stadium, Warsaw | POL | GRE |
1002 | 8 June 2012 | Stadion Miejski (Wroclaw) | RUS | CZE |
1003 | 12 June 2012 | Stadion Miejski (Wroclaw) | GRE | CZE |
1004 | 12 June 2012 | National Stadium, Warsaw | POL | RUS |
... |
matchid | teamid | player | gtime | |
---|---|---|---|---|
1001 | POL | Robert Lewandowski | 17 | |
1001 | GRE | Dimitris Salpingidis | 51 | |
1002 | RUS | Alan Dzagoev | 15 | |
1002 | RUS | Roman Pavlyuchenko | 82 | |
... |
id | teamname | coach | ||
---|---|---|---|---|
POL | Poland | Franciszek Smuda | ||
RUS | Russia | Dick Advocaat | ||
CZE | Czech Republic | Michal Bilek | ||
GRE | Greece | Fernando Santos | ||
... |
JOIN と UEFA EURO 2012
このチュートリアルでは JOIN
を紹介します。これで2個かそれ以上のテーブルを扱えるようになります。
ここのテーブルには UEFA EURO 2012 Football Championship in Poland and Ukraine(欧州選手権サッカーチャンピオンシップ イン ポーランド・ウクライナ) の全試合のゴールが格納されています。
mysqlフォーマットのデータはこちらから http://sqlzoo.net/euro2012.sql (訳者注 リンク切れ)
最初の例としてラストネームが Bender である選手のゴール記録が示されている。
「*」でテーブルの全フィールド(カラム)を宣言する。これは matchid, teamid, player, gtime
を短く書く方法である。
matchid と player 名をドイツ(Germany)チームの全ゴールについて表示する。ドイツプレイヤーを識別するには、次を確認:
teamid = 'GER'
SELECT * FROM goal
WHERE player LIKE '%Bender'
SELECT matchid, player
FROM goal
WHERE teamid LIKE 'GER'
上記のクエリ―では、Lars Benderのゴールは ゲーム 1012 で確認できる。さて、この試合でどの2チームがプレイしていたか知りたい。
goal
テーブルでは試合番号は matchid
だが、game
テーブルでは id
となっていることに注意する。
試合 1012 の情報を知るには game の該当する行を参照する。
試合 1012 の id, stadium, team1, team2 を表示する。
SELECT id,stadium,team1,team2
FROM game
SELECT id,stadium,team1,team2
FROM game
WHERE id=1012
JOIN
を利用して、2つのステップ(訳者注 上記1.と2.のこと)を単独のクエリ―に統合できる。
gameとgoalの詳細を得るには、
SELECT * FROM game JOIN goal ON (id=matchid)
FROM節はgoalテーブルとgameテーブルのデータを統合する。
ON で gameの行と goalの行を、goalテーブルのidをgameの matchidと一致させて対応させる。
(もっと明確に言うとすれば、こう言う。ON (game.id=goal.matchid)
得点が有るたびに、goalテーブルから playerを表示して、stadium 名は game ゲーブルから表示する。
ドイツの全ゴールについて player, teamid ,stadium, mdate を表示するように修正する。
SELECT player,stadium
FROM game JOIN goal ON (id=matchid)
SELECT player,teamid,stadium,mdate
FROM game JOIN goal ON (id=matchid)
WHERE teamid='GER'
上の問題と同様に JOIN を利用して、
Marioという名前の選手のゴールについて、team1, team2 , player を表示する。player LIKE 'Mario%'
SELECT team1, team2, player
FROM game JOIN goal ON (id=matchid)
WHERE player LIKE 'Mario%'
eteam には各参加国のコーチが記載されている。
JOIN で goal を eteam に結合する。
goal JOIN eteam on teamid=id
最初の10分間でゴールしたという条件で、 player, teamid, coach, gtime を表示。gtime<=10
SELECT player, teamid, gtime
FROM goal
WHERE gtime<=10
SELECT player, teamid, coach, gtime
FROM goal JOIN eteam ON (teamid=id)
WHERE gtime<=10
game
と eteam
を結合するには、
game JOIN eteam ON (team1=eteam.id)
または、
game JOIN eteam ON (team2=eteam.id)
id
は game
と eteam
で同じ名前なので、単にid
と書く代わりにeteam.id
と書かねばならないことに注意する。
team1のコーチcoachが 'Fernando Santos' となる試合日mdateとチーム名teamnameを表示。
SELECT mdate,teamname
FROM game JOIN eteam ON (team1=eteam.id)
WHERE coach='Fernando Santos'
'National Stadium, Warsaw' スタジアムで開催された試合でゴールした選手を表示する。
SELECT player
FROM goal JOIN game ON (id=matchid)
WHERE stadium = 'National Stadium, Warsaw'
より難しい問題
代わりに、ドイツと対戦して、ゴールした選手の名前を全て表示する。
ドイツプレイヤーではないプレイヤーで、GER が team1 または team2 のidに現れるプレイヤーを選択する。
teamid!='GER'
でドイツプレイヤーをリストアップするのを防ぐ。
DISTINCT
でプレイヤーの名前が繰り返し登場するのを止める。
SELECT player, gtime
FROM game JOIN goal ON matchid = id
WHERE (team1='GER' AND team2='GRE')
SELECT DISTINCT player
FROM game JOIN goal ON matchid = id
WHERE (team1 = 'GER' OR team2 = 'GER')
AND teamid!='GER'
COUNT(*) を SELECT で使用し、GROUP BY teamname する。(teamnameでグループにする)
SELECT teamname, player
FROM eteam JOIN goal ON id=teamid
ORDER BY teamname
SELECT teamname,COUNT(teamid)
FROM eteam JOIN goal ON id=teamid
GROUP BY teamname
SELECT stadium,COUNT(1)
FROM goal JOIN game ON id=matchid
GROUP BY stadium
SELECT matchid,mdate, team1, team2,teamid
FROM game JOIN goal ON matchid = id
WHERE (team1 = 'POL' OR team2 = 'POL')
SELECT matchid,mdate,COUNT(teamid)
FROM game JOIN goal ON matchid = id
WHERE (team1 = 'POL' OR team2 = 'POL')
GROUP BY matchid,mdate
SELECT matchid,mdate,COUNT(teamid)
FROM game JOIN goal ON matchid = id
WHERE (teamid='GER')
GROUP BY matchid,mdate
mdate | team1 | score1 | team2 | score2 |
---|---|---|---|---|
1 July 2012 | ESP | 4 | ITA | 0 |
10 June 2012 | ESP | 1 | ITA | 1 |
10 June 2012 | IRL | 1 | CRO | 3 |
... |
注意) 全得点状況が、記録されている。もし、チーム名が goal に記録されていれば、 その時点でチームが1得点していることにななり、チーム名が記載されていなければ、得点は0点である。
チーム名有り → 1
チーム名なし → 0
この、得点状況を 1と0 に CASE WHEN で変換した結果をSUM で集計すれば、そのチームの得点を集計できる。
結果は、日程順で並べ替えて出力する(日程が同じなら、idの順番)。
SELECT mdate,
team1,
CASE WHEN teamid=team1 THEN 1 ELSE 0 END score1
FROM game JOIN goal ON matchid = id
SELECT mdate,
team1,
SUM(CASE WHEN teamid=team1 THEN 1 ELSE 0 END) score1,
team2,
SUM(CASE WHEN teamid=team2 THEN 1 ELSE 0 END) score2
FROM game LEFT JOIN goal ON matchid = id
GROUP BY mdate,matchid,team1,team2
古いチュートリアル(訳者注 卓球オリンピックのデータベース)
次のチュートリアル は映画のデータベースに関してやや複雑な結合を含む。