2010-10-04 33 views
0

我需要從3個不同的表中獲取數據。我知道關於JOIN的基本知識,但是涉及到更復雜的查詢,例如使用JOIN從3個或更多表中獲取數據時,我有點困惑,我開始玩查詢,寫下對我有意義的查詢,如下一個:這是MySQL查詢一個JOIN,一個普通的查詢或兩者?

SELECT movies.imdbID, 
    movies.title, 
    movies.year, 
    movie_ratings.votes, 
    movie_ratings.total_value, 
    movie_ratings_external.votes, 
    movie_ratings_external.total_value 
FROM movies, movie_ratings_external 
LEFT JOIN movie_ratings ON movie_ratings.imdbID = movie_ratings_external.imdbID 
WHERE movies.imdbID = movie_ratings_external.imdbID 
ORDER BY movie_ratings.votes DESC, movie_ratings_external.votes DESC 
LIMIT 30 

此查詢適用。我從正確的表格中選擇了字段並按照正確的方式排序,但我認爲我正在混合一些東西(比如定期查詢兩個表並在兩個表之間加入JOIN),我相信這是更好/更高效的方法來完成同一個purpouse。

任何數據庫怪胎可用?

回答

1

修改您的查詢只是有點。其他一切都非常重要。

我不完全確定你稱之爲「常規查詢」,但聯接幾乎是常規查詢的基本部分。

在您的舊查詢中,這部分FROM movies, movie_ratings_external基本上是CROSS JOIN。用JOIN替換它(我用LEFT JOIN假設你總是想要返回所有的電影,但基本意圖是,與在WHERE中過濾的CROSS JOIN更加低效,因爲你操縱更多的ROWS - 尤其是不必要的)

想想這樣。 SELECT中的每個Join語句返回一組行,然後與JOIN中的下一個表聯接。這個想法應該是儘可能逐步嘗試逐行過濾行,這樣你就不會得到不必要的元組。其中ON語句進來那。

刪除

SELECT 
    movies.imdbID, 
    movies.title, 
    movies.year, 
    movie_ratings.votes, 
    movie_ratings.total_value, 
    movie_ratings_external.votes, 
    movie_ratings_external.total_value 
FROM movies 
LEFT OUTER JOIN movie_ratings_external 
    ON movies.imdbID = movie_ratings_external.imdbID 
LEFT JOIN movie_ratings 
    ON movie_ratings.imdbID = movie_ratings_external.imdbID 
ORDER BY movie_ratings.votes DESC, movie_ratings_external.votes DESC 
LIMIT 30 

希望幫助!

1

您正在做2個連接。然而,你正在混合你的語法,這會降低可讀性。

要麼

SELECT movies.imdbID, 
    movies.title, 
    movies.year, 
    movie_ratings.votes, 
    movie_ratings.total_value, 
    movie_ratings_external.votes, 
    movie_ratings_external.total_value 
FROM movies 
LEFT JOIN movie_ratings_external ON movies.imdbID = movie_ratings_external.imdbID 
LEFT JOIN movie_ratings ON movie_ratings.imdbID = movie_ratings_external.imdbID 
ORDER BY movie_ratings.votes DESC, movie_ratings_external.votes DESC 
LIMIT 30 

或類似這樣的

SELECT movies.imdbID, 
    movies.title, 
    movies.year, 
    movie_ratings.votes, 
    movie_ratings.total_value, 
    movie_ratings_external.votes, 
    movie_ratings_external.total_value 
FROM movies, movie_ratings_external, movie_ratings 
WHERE movies.imdbID = movie_ratings_external.imdbID 
    AND movie_ratings.imdbID = movie_ratings_external.imdbID 
ORDER BY movie_ratings.votes DESC, movie_ratings_external.votes DESC 
LIMIT 30 

我也不清楚爲什麼你左側的接合部。如果某個特定電影的評分可能不存在,您可能希望加入該電影表。

如果這是你的意圖,你的查詢應該看起來像這樣。

SELECT movies.imdbID, 
    movies.title, 
    movies.year, 
    movie_ratings.votes, 
    movie_ratings.total_value, 
    movie_ratings_external.votes, 
    movie_ratings_external.total_value 
FROM movies 
LEFT OUTER JOIN movie_ratings_external ON movies.imdbID = movie_ratings_external.imdbID 
LEFT OUTER JOIN movie_ratings ON movies.imdbID = movie_ratings.imdbID 
ORDER BY movie_ratings.votes DESC, movie_ratings_external.votes DESC 
LIMIT 30 
0

你使用

FROM tableA, tableB 
WHERE tableA.abc = tableB.def 

第一個語法是正規內加入,確實另一種語法,你可以在某些的DBMS,例如Informix的使用只有語法 - 這兩個應該是完全當量。不過,我認爲混合和匹配語法會令人困惑,所以我會選擇一個並堅持下去。真正的測試是在切換之前和之後檢查mysql查詢計劃,但如果它有所不同,我會非常驚訝。

效率:只要您在所有右欄 - 即所有三張桌子上的imdbID欄都有索引 - 我看不出任何可以改進的地方。我不認爲你也需要在你訂購的專欄上有一個索引,但如果你正在尋求改進,這可能值得測試。

0

查詢沒有錯。但我更喜歡類似以下的東西 - 爲了可讀性:

SELECT Movie.imdbID 
,  Movie.title 
,  Movie.year 
,  Rating.votes 
,  Rating.total_value 
,  ExternalRating.votes 
,  ExternalRating.total_value 

FROM movies Movie 
    LEFT JOIN 
     movie_ratings_external ExternalRating 

ON  Movie.imdbID = ExternalRating.imdbID 

    LEFT JOIN movie_ratings Rating 

ON  Rating.imdbID = ExternalRating.imdbID 

ORDER BY 
     Rating.votes DESC 
,  ExternalRating.votes DESC