2015-05-24 54 views
0

我有返回相同的數據的兩個不同的查詢:查詢區別:分組JOIN VS直列JOIN

+---------+-------------------------------+----------+ 
| title | body       | username | 
+---------+-------------------------------+----------+ 
| Welcome | You got a cool forum here  | john  | 
| Welcome | Great topics.     | boyd  | 
| Welcome | Nice to have you as members | cris  | 
| Looking | I have the time and knowlegde | boyd  | 
| Looking | I'm fully qualified for this | joe  | 
+---------+-------------------------------+----------+ 

查詢我:

SELECT posts.title,comments.body,users.username 
FROM posts 
    LEFT JOIN (
     users INNER JOIN comments ON users.id = comments.user_id 
    ) ON posts.id = comments.post_id 

查詢II:

SELECT posts.title,comments.body,users.username 
FROM posts 
    LEFT JOIN comments ON posts.id = comments.post_id 
    INNER JOIN users ON users.id = comments.user_id 

而且這些是我的表格:

USERS 
+----+----------+ 
| id | username | 
+----+----------+ 
| 1 | john  | 
| 2 | boyd  | 
| 3 | ella  | 
| 4 | cris  | 
| 5 | joe  | 
| 6 | esses | 
| 18 | test2 | 
+----+----------+ 
      POSTS 
+----+-----------------------+ 
| id | title     | 
+----+-----------------------+ 
| 1 | Welcome    | 
| 2 | Looking for moderator | 
+----+-----------------------+ 

         COMMENTS 
+---------+---------+------------------------------------------+ 
| post_id | user_id | body          | 
+---------+---------+------------------------------------------+ 
|  1 |  1 | You got a cool forum here    | 
|  1 |  2 | Great topics.       | 
|  1 |  4 | Nice to have you as members    | 
|  2 |  2 | I have the time and knowlegde to do this | 
|  2 |  5 | I'm fully qualified for this job   | 
+---------+---------+------------------------------------------+ 

我的問題是:這兩個查詢之間的真正區別是什麼?

編輯:這是EXPLAIN EXTENDED結果:

查詢我:

- EXPLAIN EXTENDED

+----+-------------+----------+--------+---------------+---------+---------+----------------------+------+----------+-------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref     | rows | filtered | Extra  | 
+----+-------------+----------+--------+---------------+---------+---------+----------------------+------+----------+-------------+ 
| 1 | SIMPLE  | posts | ALL | NULL   | NULL | NULL | NULL     | 2 | 100.00 | NULL  | 
| 1 | SIMPLE  | comments | ALL | NULL   | NULL | NULL | NULL     | 5 | 100.00 | Using where | 
| 1 | SIMPLE  | users | eq_ref | PRIMARY  | PRIMARY | 4  | app.comments.user_id | 1 | 100.00 | NULL  | 
+----+-------------+----------+--------+---------------+---------+---------+----------------------+------+----------+-------------+ 

- SHOW警告

+-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| Level | Code | Message                                                                             | 
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| Note | 1003 | /* select#1 */ select `app`.`posts`.`title` AS `title`,`app`.`comments`.`body` AS `body`,`app`.`users`.`username` AS `username` from `app`.`posts` left join (`app`.`users` join `app`.`comments`) on(((`app`.`posts`.`id` = `app`.`comments`.`post_id`) and (`app`.`users`.`id` = `app`.`comments`.`user_id`))) where 1 | 
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 

查詢II:

- EXPLAIN EXTENDED

+----+-------------+----------+--------+---------------+---------+---------+----------------------+------+----------+----------------------------------------------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref     | rows | filtered | Extra            | 
+----+-------------+----------+--------+---------------+---------+---------+----------------------+------+----------+----------------------------------------------------+ 
| 1 | SIMPLE  | comments | ALL | NULL   | NULL | NULL | NULL     | 5 | 100.00 | Using where          | 
| 1 | SIMPLE  | users | eq_ref | PRIMARY  | PRIMARY | 4  | app.comments.user_id | 1 | 100.00 | NULL            | 
| 1 | SIMPLE  | posts | ALL | PRIMARY  | NULL | NULL | NULL     | 2 | 100.00 | Using where; Using join buffer (Block Nested Loop) | 
+----+-------------+----------+--------+---------------+---------+---------+----------------------+------+----------+----------------------------------------------------+ 

- SHOW警告

+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| Level | Code | Message                                                                          | 
+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| Note | 1003 | /* select#1 */ select `app`.`posts`.`title` AS `title`,`app`.`comments`.`body` AS `body`,`app`.`users`.`username` AS `username` from `app`.`posts` join `app`.`comments` join `app`.`users` where ((`app`.`posts`.`id` = `app`.`comments`.`post_id`) and (`app`.`users`.`id` = `app`.`comments`.`user_id`)) | 
+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
+0

我不認爲有任何區別。 – Barmar

+0

運行EXPLAIN EXTENDED ...;其次是SHOW WARNINGS;在這兩個查詢 – Strawberry

+0

@草莓,@巴爾馬爾。我只是添加了解釋擴展結果。它看起來像第一個查詢執行少一個額外的查詢。 – boyd

回答

0

在這兩個查詢之間沒有概念上的差異,但爲了提高性能,它能夠更好地儘快縮小時間成績表儘可能先連接更大的表格,然後只選擇所需的字段而不是全部。

+0

從性能角度來看最好的查詢是什麼? – boyd

+0

這取決於你的桌子的大小。你必須預測表格的大小,並根據這個寫你的查詢 – Mahmoud

0

我覺得我說得很對,查詢2在功能上等同的:

select p.title 
, c.body 
, u.username 
from posts p 
join comments c 
on p.id = c.post_id 
join users u 
    on u.id = c.user_id 

而查詢1等同於這個

select p.title 
, c.body 
, u.username 
from posts p 
join comments c 
on p.id = c.post_id 
left 
join users u 
on u.id = c.user_id 
where 1 
+0

所以只有一個語法上的差異? – boyd

+0

不會的。除非我錯了(我可能會),這裏有一個邏輯上的區別。但是你可以很容易地用你的數據集來演示 – Strawberry

1

加入的邏輯處理,從左至右除非用圓括號覆蓋它。

Q1: posts LEFT (users INNER comments) 

posts留給加入到(users INNER comments)結果,這將導致所有行posts與NULL值,其中連接條件不計算爲TRUE

Q2: posts LEFT comments INNER users 

現在posts是左連接到comments第一,無法連接的comments的列爲空。然後使用內部連接將此結果加入users。但由於comments.user_id中的NULL,因外連接而添加的行將再次被刪除。實際上,這與內部連接所有三個表格相同。

+0

因此,除了語法之外,這些查詢之間沒有區別嗎? – boyd

+0

@boyd:當然,這是一個不同的結果集。但只有**你**知道哪一個是正確的:-) – dnoeth