2014-09-21 24 views
1

我在MySQL數據庫中的兩個表是這樣的錶行:MySQL的加入,基於最低的單元格值

產品:

product_id | product_name 
-----------+------------- 
1   | shirt 
2   | pants 
3   | socks 

PRODUCT_SUPPLIER:(ID是主鍵)

id | supplier_id | product_id | part_no | cost 
----+---------------+--------------+-----------+-------- 
1 | 1   | 1   | s1p1  | 5.00 
2 | 1   | 2   | s1p2  | 15.00 
3 | 1   | 3   | s1p3  | 25.00 
4 | 2   | 1   | s2p1  | 50.00 
5 | 2   | 2   | s2p2  | 10.00 
6 | 2   | 3   | s2p3  | 5.00 

我的目標是連接這些表格併爲每個產品輸出單行的查詢,這些產品與相應供應商行的所有字段以最低成本相連,如下所示:

product_id | product_name | supplier_id | part_no | cost 
-----------+---------------+---------------+------------+--------- 
1   | shirt   | 1    | s1p1  | 5.00 
2   | pants   | 2    | s2p2  | 10.00 
3   | socks   | 2    | s3p3  | 5.00 

目前我確實有以下查詢寫入似乎工作,但我想從任何更有經驗的SQL用戶知道是否有更清潔,更有效或更好的解決方案?或者,如果我的代碼有什麼本質上的錯誤?

SELECT p.product_id, p.product_name, s. supplier_id, s.part_no, s.cost 
FROM product p 
LEFT JOIN product_supplier s ON 
    (s.id = (SELECT s2.id 
      FROM product_supplier s2 
      WHERE s2.product_id = p.product_id 
      ORDER BY s2.cost LIMIT 1)); 

回答

1

我會跑:

select p.product_id, p.product_name, s.supplier_id, s.part_no, s.cost 
    from product p 
    join product_supplier s 
    on p.product_id = s.product_id 
    join (select product_id, min(cost) as min_cost 
      from product_supplier 
     group by product_id) v 
    on s.product_id = v.product_id 
    and s.cost = v.min_cost 

我沒有看到一個外點加入。每個產品都在product_supplier表上嗎?如果不是,那麼外部連接是有意義的(如果是這種情況,則將連接更改爲內聯視圖別名爲v以上的左連接)。

上面可能比​​你的查詢要快一點,因爲子查詢是不是爲每一行運行。您當前的子查詢是相關的並且與每行產品有關。

如果你想消除關係並且不關心任意這樣做,你可以在結果的末尾添加一個隨機數,把查詢放入內聯視圖,然後選擇最低/最高/等。每組的隨機數。這裏有一個例子:

select product_id, product_name, supplier_id, part_no, cost, min(rnd) 
    from (select p.product_id, 
       p.product_name, 
       s.supplier_id, 
       s.part_no, 
       s.cost, 
       rand() as rnd 
      from product p 
      join product_supplier s 
      on p.product_id = s.product_id 
      join (select product_id, min(cost) as min_cost 
       from product_supplier 
       group by product_id) v 
      on s.product_id = v.product_id 
      and s.cost = v.min_cost) x 
group by product_id, product_name, supplier_id, part_no, cost 

如果由於某種原因,你不希望隨機#回來輸出,就可以把整個查詢到上方內嵌視圖,並選擇所有列,但隨機#從中。

+0

謝謝..這正是我所希望的那種輸入。我仍然在學習sql,第二次連接的語法(內聯視圖?)對我來說是全新的。我欣賞微調。 – billynoah 2014-09-21 00:20:26

+0

並且是的,理論上每個產品都應該至少有一個對應的供應商行 - 儘管實際上很難說這是否會始終是這種情況 – billynoah 2014-09-21 00:22:19

+1

from子句中的子查詢被稱爲幾件事情,「內聯視圖'是一個通常由與oracle一起工作的人使用的術語,有些人也稱之爲'子選擇'或'派生表',或者只是一個子查詢。基本上,如果你自己運行這個查詢(我把它作爲v的那個),你會得到每個產品的最低成本,把查詢放入一個內聯視圖中,因爲更大的查詢的一部分允許你加入它即,將行限制爲那些成本等於給定項目的最低成本的行。 – 2014-09-21 00:23:34

相關問題