2010-09-08 26 views
3

說我有這三個表:留下空結果加入時沒有找到匹配

Table: Baskets 
id | name 
1  Sale 
2  Premium 
3  Standard 
4  Expired 

Table: Fruit 
id | name | basketid 
1  Apples 1 
2  Oranges 2 
3  Grapes 3 
4  Apples 2 
5  Apples 4 

Table: Veggies 
id | name | basketid 
1  Carrots  1 
2  Peas  2 
3  Asparagus 1 

它可能看起來像第二兩個表應該剛剛被一個表叫生產,但在實際情況有是他們成爲不同表格的好理由。如果籃子在水果或素食表中有行,我需要編寫一個返回行的連接。我以爲我可以用兩個左連接,像這樣實現:

Select Baskets.*, fruit.name as fruit, 
veggies.name as veggies 
from Baskets 
left join Fruit on Baskets.id = Fruit.basketid 
left join veggies on Baskets.id = Veggies.basketid 
where Baskets.id = 2; 

但這種說法在我想是空字段返回值。實際輸出:

id | name  | fruit | veggies 
2  Premium Oranges  Peas 
2  Premium Apples  Peas 

輸出我想:

id | name  | fruit | veggies 
2  Premium Oranges  
2  Premium Apples  
2  Premium    Peas 

我怎樣才能做到這一點?

+0

誰不愛過期的水果和蔬菜? :) – NullUserException 2010-09-08 16:14:13

+1

@NullUserException:那個笑話已經過期了:p – 2010-09-08 16:15:16

+0

很高興我沒有在這個例子中包含完全被寵壞和爛的籃子! – Todd 2010-09-08 17:18:01

回答

4

您需要工會的水果和蔬菜的表到一個關係,你加入對抗,一拉:

Select Baskets.*, produce.fruitname as fruit, produce.veggiename as veggies 
from Baskets 
left join (SELECT basketid, name as fruitname, NULL as veggiename 
      FROM fruit 
      UNION 
      SELECT basketid, NULL, name 
      FROM veggies) produce 
     ON baskets.id = produce.basketid 
where Baskets.id = 2; 
+0

巧妙地使用union聲明(我以前沒有見過)。但即使水果或蔬菜表中不存在任何匹配記錄,這也會返回一行。我想我解決了這個問題,從左連接變成了常規內連接。 – Todd 2010-09-08 16:57:23

+1

如果在兩者中都不可能有記錄,則使用UNION ALL。 – HLGEM 2010-09-08 17:48:59

2

這個查詢將返回任何行,如果有什麼籃子:

SELECT baskets.*, fruit.name AS fruit, NULL AS veggie 
FROM baskets 
JOIN fruit 
ON  fruit.basketId = baskets.id 
WHERE baskets.Id = 2 
UNION 
SELECT baskets.*, NULL, veggie.name 
FROM baskets 
JOIN veggies 
ON  veggies.basketId = baskets.id 
WHERE baskets.Id = 2 

這個查詢將返回一行有兩個NULLS如果沒有在籃下:

SELECT baskets.*, fruit.name AS fruit, NULL AS veggie 
FROM baskets 
LEFT JOIN 
     fruit 
ON  fruit.basketId = baskets.id 
WHERE baskets.Id = 2 
UNION 
SELECT baskets.*, NULL, veggie.name 
FROM baskets 
LEFT JOIN 
     veggies 
ON  veggies.basketId = baskets.id 
WHERE baskets.Id = 2 

這假定fruit.nameveggie.name都不是可空和唯一的。

該查詢是一樣的,但以往可以更高效:

SELECT baskets.*, fruit.name AS fruit, NULL AS veggie 
FROM baskets 
JOIN fruit 
ON  fruit.basketId = baskets.id 
WHERE baskets.Id = 2 
UNION ALL 
SELECT baskets.*, NULL, veggie.name 
FROM baskets 
JOIN veggies 
ON  veggies.basketId = baskets.id 
WHERE baskets.Id = 2 
UNION ALL 
SELECT baskets.*, NULL, NULL 
FROM baskets 
LEFT JOIN 
     fruit 
ON  fruit.basketId = baskets.id 
LEFT JOIN 
     veggies 
ON  veggies.basketId = baskets.id 
WHERE baskets.Id = 2 
     AND fruit.basketId IS NULL 
     AND veggies.basketId IS NULL 

,並且不承擔任何事情。

+0

我不認爲這會像左連接一樣。也就是說,如果水果或蔬菜中沒有給定basketId的條目,則不會返回行,而會返回沒有行的空行和素食字段。 – ngroot 2010-09-08 16:20:24

+0

@ngroot:查看帖子更新 – Quassnoi 2010-09-08 16:28:07

+0

@ngroot:似乎我誤以爲@op :)實際上,@op想要「編寫一個連接,如果籃子在水果或素食表中有行,則返回行」,這似乎是一個'INNER JOIN'。 – Quassnoi 2010-09-08 16:34:48