2012-08-10 78 views
1
select distinct p.product_id from cscart_products p 
    left join product_bikes pb on p.product_id = pb.product_id 
    left join cscart_product_options po on po.product_id = p.product_id 
    left join cscart_product_option_variants pov on pov.option_id = po.option_id 
    left join variant_bikes vb on vb.variant_id = pov.variant_id 
    where pb.bike_id = 111 or vb.bike_id = 111 

和:這兩個mysql查詢爲什麼不同?

select distinct p.product_id from cscart_products p 
    left join product_bikes pb on p.product_id = pb.product_id and pb.bike_id = 111 
    left join cscart_product_options po on po.product_id = p.product_id 
    left join cscart_product_option_variants pov on pov.option_id = po.option_id 
    left join variant_bikes vb on vb.variant_id = pov.variant_id and vb.bike_id = 111 

返回不同的結果集,爲什麼呢?

回答

4

第一個查詢有一個或WHERE子句中:

WHERE pb.bike_id = 111 OR vb.bike_id = 111 

第二個查詢有效地具有,而是經由所述條件:

LEFT JOIN product_bikes pb ON p.product_id = pb.product_id AND pb.bike_id = 111 
... 
LEFT JOIN variant_bikes vb ON vb.variant_id = pov.variant_id AND vb.bike_id = 111 

獎金的問題:是有沒有一種方法可以使連接的行爲保持不變,並從性能較小的連接中受益?

還有就是要編寫查詢的方式,但它不一定是任何更快,因爲方法(即我想的)使用UNION:

select distinct p.product_id from cscart_products p 
    left join product_bikes pb on p.product_id = pb.product_id and pb.bike_id = 111 
    left join cscart_product_options po on po.product_id = p.product_id 
    left join cscart_product_option_variants pov on pov.option_id = po.option_id 
    left join variant_bikes vb on vb.variant_id = pov.variant_id -- and vb.bike_id = 111 
UNION 
select distinct p.product_id from cscart_products p 
    left join product_bikes pb on p.product_id = pb.product_id -- and pb.bike_id = 111 
    left join cscart_product_options po on po.product_id = p.product_id 
    left join cscart_product_option_variants pov on pov.option_id = po.option_id 
    left join variant_bikes vb on vb.variant_id = pov.variant_id and vb.bike_id = 111 

有可能是一個更好的辦法這樣做的,例如,你有一個UNION子查詢,沿着線:

SELECT DISTINCT p.product_id 
    FROM  cscart_products    AS p 
    LEFT JOIN cscart_product_options   AS po ON po.product_id = p.product_id 
    LEFT JOIN cscart_product_option_variants AS pov ON pov.option_id = po.option_id 
    LEFT JOIN (SELECT vb.product_id FROM variant_bikes AS vb WHERE vb.bike_id = 111 
      UNION 
      SELECT pb.product_id FROM product_bikes AS pb WHERE pb.bike_id = 111 
      ) AS pv ON pv.product_id = p.product_id 

由於你不是(在示例中)從cscart_product_optionscscart_product_options_variants表中選擇的數據,則可以消除這些往復在查詢中。你還應該看看LEFT JOIN和子查詢是否合適。我認爲你更想要一個內部連接。可以做更多的工作來改善績效。

+0

好極了:)謝謝你不會讓我給你獎勵你11分鐘的答案。獎金問題:有沒有聯接的方式,使其行爲相同,並從性能較小的聯接中受益? – Wolfe 2012-08-10 21:37:41

+1

在第二個查詢的末尾添加'WHERE pb.bike_id IS NOT NULL或vb.bike_id IS NOT NULL'。 – Barmar 2012-08-10 21:42:46

+0

其他連接類型是否也可以工作,例如對這些連接Barmar使用完全連接? – Wolfe 2012-08-10 21:47:56

1

除了喬納森所說的。在第一個查詢中,WHERE強制它不會得到任何結果,除非(pb.bike_id = 111或vb.bike_id = 111)爲真。在第二個查詢中,即使只有一行可以通過LEFT JOIN加入,您仍將獲得所有DISTINCT [product_id]。

如果你從第二個查詢中獲得很多結果,那就是這樣。看到這種更簡單的方法是將更多的在你的SELECT這樣:

SELECT p.product_id, pb.bike_id ... 

如果你這樣做,第一查詢將在它顯示每個產品111你會注意到,但第二個查詢將有很多pb.bike_id的NULL值。

有意義嗎?

+0

是的,謝謝:) – Wolfe 2012-08-10 22:05:10