2014-09-21 13 views
1

У меня есть две таблицы в базе данных MySQL, как это:MySQL Присоединяйтесь строку таблицы на основе минимального значения ячейки

ПРОДУКЦИИ:

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

PRODUCT_SUPPLIER: (идентификатор первичный ключ)

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

+0

и да, теоретически, каждый продукт должен иметь по крайней мере одну соответствующую строку поставщика, хотя на самом деле трудно сказать, будет ли это всегда так. – billynoah

+1

Подзапрос в предложении from упоминается как несколько вещей, 'inline view '- термин, обычно используемый людьми, работающими с oracle, некоторые также называют его «подвыборкой» или «производной таблицей» или просто как подзапрос. В принципе, если бы вы сами запускали этот запрос (тот, который я назвал v), вы получите самую низкую стоимость для каждого продукта, поставив этот запрос в встроенное представление как часть более крупного запроса, чтобы вы могли присоединиться к нему , т.е. ограничивая строки теми, где стоимость равна самой низкой стоимости для данного элемента. –

Смежные вопросы