2013-05-20 90 views
1

我對MySQl中的內部聯接有疑問。從我對MySQL的有限理解來看,內部聯接生成的結果表只包含兩個表中存在的行。也就是說,例如,如果table1包含Joe的行和Sally的行,並且table2僅包含Sally的行,則內部聯接將只包含一行:Sally的行。MySQL內部加入結果

例如:

在其中包含2個表的數據庫,

表1(PET)

petName petType 
Unicorn Horse 
Pegasus Horse 
Lion Cat 

表2(彩色)

petName petColor 
Unicorn white 
Unicorn silver 
Fish Gold 

使用查詢

SELECT * FROM Pet,Color WHERE Pet.petName = Color.petName 

爲什麼查詢的結果?

petName petType petName petColor 
Unicorn Horse Unicorn white 
Unicorn Horse Unicorn silver 

爲什麼在表1中只有1個「獨角獸馬」時,第二排中會出現「獨角獸馬」?我是否正確地說MySQL在表1和表2中與術語「獨角獸」相匹配,並且列出了兩個表中具有「獨角獸」一詞的行。然而,由於這樣做會導致

petName petType petName petColor 
Unicorn Horse Unicorn white 
< NULL > Unicorn silver 

MySQL的自動替換在表中的一個,因爲它在查詢中使用的「麒麟」的關鍵字匹配行「麒麟馬」的價值?

如果是這樣,那麼這又是什麼意思呢,因爲MySQL只會在第二行給我多餘的數據,而我沒有這個用處呢?此外,我將能夠通過使用來解決此

SELECT * FROM Pet LEFT JOIN Color 
ON Pet.petName=Color.petName 
WHERE Pet.petName="Unicorn"? 

我碰到這個例子在PHP MYSQL &傻瓜來了,也似乎無法得到它。 如果某種靈魂能夠澄清這一點,我將不勝感激。

回答

2

如果執行SELECT * from Pet, Color(不WHERE條款),你會得到如下回:

petName petType petName petColor 
Unicorn Horse Unicorn white 
Pegasus Horse Unicorn white 
Lion Cat  Unicorn white 
Unicorn Horse Unicorn silver 
Pegasus Horse Unicorn silver 
Lion Cat  Unicorn silver 
Unicorn Horse Fish Gold 
Pegasus Horse Fish Gold 
Lion Cat  Fish Gold 

這被稱爲CROSS JOIN; SQL服務器將從表1中取出每一行並將其與表2中的每一行進行匹配。

當您添加WHERE Pet.petName = Color.petName時,SQL服務器將過濾掉其中子句爲不真實的所有行。這樣,由於只petName與定義petColorUnicorn,你只剩下

petName petType petName petColor 
Unicorn Horse Unicorn white 
Unicorn Horse Unicorn silver 

有你的查詢,而不是一直WHERE Pet.petName != Color.petName,你將有補,或

petName petType petName petColor 
Pegasus Horse Unicorn white 
Lion Cat  Unicorn white 
Pegasus Horse Unicorn silver 
Lion Cat  Unicorn silver 
Unicorn Horse Fish Gold 
Pegasus Horse Fish Gold 
Lion Cat  Fish Gold 

如果你只是想從寵物一行其中顏色定義,你可以使用

SELECT * FROM Pet 
    WHERE EXISTS (SELECT * FROM Color where Color.petName = Pet.petName) 

這將返回

​​

此查詢本質上意味着「選擇從Pet所有行存在對寵物定義的至少一個Color,通過名稱」。

這被稱爲半連接,因爲SQL服務器可能會在幕後與Color進行連接,但在結果集中沒有返回Color的數據。由於沒有返回Color數據,因此您將只從Pet中獲取每行一次,而不管爲任何給定的petName定義的Color行的數量。

+0

SELECT * FROM寵物WHERE EXISTS(SELECT * FROM Color其中Color.petName = Pet.petName)以純英文翻譯成「選擇表Pet中的行(其中列petName中的數據與數據匹配)在表Color中的petName列中?我問這是因爲我還不太確定MySQL的語法。謝謝! –

+0

@ Ken--更新了包含解釋的答案。 –

3

結果如預期。您將在兩個表格中加入列表PetName的兩個表格。 Unicorn Horse從表Pet在結果集中顯示兩次,因爲它在表Color上的兩個記錄上匹配。

爲了進一步獲得更多的知識有關加入,請訪問以下鏈接:

1

哪裏有「每單列一個側面上其他多行」,那麼,單行值被重複。

因此,這是正確的:

petName petType petName petColor 
Unicorn Horse Unicorn white 
Unicorn Horse Unicorn silver 

SQL不能與INNER JOIN生成此。

petName petType petName petColor 
Unicorn Horse Unicorn white 
< NULL > Unicorn silver 

就這麼簡單。

+0

對不起打斷,但是做正確的連接並沒有給你顯示的結果。 – Walter

+0

@Zeus:解釋爲什麼請 – gbn

+2

這裏:http://sqlfiddle.com/#!2/f564e/2'unicorn'在另一張桌子上有一個匹配。 – Walter

0

這是預期的。

您的查詢將連接來自每個表的petName列並返回匹配的結果。這裏找到一個匹配從PET表名Unicorn Horse在顏色表顏色white,然後將其從PET表在顏色表中尋找一個第二場比賽名稱Unicorn Horse彩色silver

0

這不是MySQL正在填充在第二行的空數據中。

您的查詢字面意思是「給我的一切,從兩個表,其中PetName是馬。

至於MySQL的來講,它不知道要在寵物1號麒麟行是白色的,然後有一個額外的獨角獸不符合任何東西是銀色的,相反,它說:「我有這個有2個屬性的獨角獸,白色和銀色。根據我的第一張桌子,我知道所有的獨角獸都是馬。所以我有一匹白馬麒麟和一匹銀馬麒麟。「

至於目的,就是這樣你可以刪除多餘的數據。例如,如果每個企業有1個地址但有多個銷售人員,你不想要爲每個銷售人員存儲相同的地址,因爲那麼當需要更改時,您必須更新很多記錄。

相反,您可以說「Testco在123 Main Street。鮑勃,約翰,莎莉和弗蘭克都是Testco的銷售人員。「然後,」什麼是鮑勃的地址「這個問題的答案就是」123大街「。但是你看看Testco的記錄是爲了得到它,而不是在Bob的記錄中。

0

您必須有兩種顏色一個獨角獸寵物,所以兩行。 如果添加另一行與麒麟petname和類型蜮來的寵物,你就會有四個。

如果你想隱藏重複的數據,這是一個演示問題,每個人都是獨角獸,你根本就沒有顯示,因爲你已經擁有了,唯一的方法就是「知道」它和上面的一樣。