Mysql
如何編寫正確的查詢來加入所有這些表而不會重複?
假設我有四個表:
TABLE: players COLUMNS: id, first_name, last_name TABLE: passing_stats COLUMNS: id, year, passing_yards (several other passing columns) TABLE: rushing_stats COLUMNS: id, year, rushing_yards (several other rushing columns) TABLE: receiving_stats COLUMNS: id, year, receiving_yards (several other receiving columns)
假設 Michael Vick 的 id 為 100。我想得到他的全名和他每年的所有統計數據(傳球、衝球和接球)。
我不想要任何重複數據,這意味著 2011 年的快速統計數據應該與 2011 年的通過統計數據出現在同一行中。
編寫此查詢的最優雅的方式是什麼?謝謝。
以下將在 Postgres 中工作。在這裡測試:SQL-Fiddle,postgres-test。SQL-Server 沒有
NATURAL JOIN
,MySQL 有NATURAL
但沒有FULL
連接:SELECT id, first_name, last_name, year, passing_yards, rushing_yards, receiving_yards FROM players p NATURAL LEFT JOIN ( passing_stats pas NATURAL FULL JOIN rushing_stats rus NATURAL FULL JOIN receiving_stats rec )
SELECT p.first_name , p.last_name , year , pas.passing_yards , rus.rushing_yards , rec.receiving_yards FROM players p LEFT JOIN ( (SELECT * FROM passing_stats WHERE id = 100) pas FULL JOIN (SELECT * FROM rushing_stats WHERE id = 100) rus USING (id, year) FULL JOIN (SELECT * FROM receiving_stats WHERE id = 100) rec USING (id, year) ) USING (id) WHERE p.id = 100 ORDER BY year;
子查詢是核心功能 - 儘早減少到相關行,這應該會產生最佳性能。
@ypercube 的想法
NATURAL JOIN
甚至更短一些,但在查詢或基礎表發生更改時更容易中斷。USING
出於類似的原因,有些人甚至在較小程度上對該條款皺眉。但在這種情況下,它使查詢簡短易讀。
LEFT JOIN
返回根本沒有統計數據的球員。備用查詢
我的第一個想法基本上是@kgrittn’s query的變體。我的修復有點侵入性,所以我發布了另一個答案。需要 PostgreSQL 8.4 或更高版本。
WITH x AS (SELECT 100 AS id) , y AS ( SELECT year FROM x JOIN passing_stats USING (id) UNION SELECT year FROM x JOIN rushing_stats USING (id) UNION SELECT year FROM x JOIN receiving_stats USING (id) ) SELECT p.first_name , p.last_name , y.year , s.passing_yards , r.rushing_yards , c.receiving_yards FROM (x CROSS JOIN y) JOIN players p USING (id) LEFT JOIN passing_stats s USING (id, year) LEFT JOIN rushing_stats r USING (id, year) LEFT JOIN receiving_stats c USING (id, year) ORDER BY y.year;
db<>在這裡擺弄