2010-06-21 2 views
14

У меня есть две таблицы MySQL (продукт и истории цен), что я хотел бы присоединиться к:Как сделать "отчетливый" присоединиться к MySQL

Product стол:

Id = int 
Name = varchar 
Manufacturer = varchar 
UPC = varchar 
Date_added = datetime 

Price_h стол:

Id = int 
Product_id = int 
Price = int 
Date = datetime 

Я могу выполнить простую LEFT JOIN:

SELECT Product.UPC, Product.Name, Price_h.Price, Price_h.Date 
FROM Product 
LEFT JOIN Price_h 
ON Product.Id = Price_h.Product_id; 

Но, как и ожидалось, если у меня есть несколько позиций для продукта в таблице истории цен, я получаю один результат по каждой исторической цене.

Как может быть объединение, которое будет возвращать только один экземпляр каждого продукта, только к нему присоединяется только самая новая запись из таблицы истории цен?

ответ

19

Использование:

SELECT p.upc, 
      p.name, 
      ph.price, 
      ph.date 
    FROM PRODUCT p 
LEFT JOIN PRICE_H ph ON ph.product_id = p.id 
    JOIN (SELECT a.product_id, 
        MAX(a.date) AS max_date 
      FROM PRICE_H a 
     GROUP BY a.product_id) x ON x.product_id = ph.product_id 
           AND x.max_date = ph.date 
+0

+1: он должен быть быстрее моего. Хотя длинный код. – a1ex07

+0

Я понимаю, почему вы говорите, что это должно быть быстрее, но мне еще предстоит найти то обстоятельство, где оно есть. Я думаю, что это может иметь какое-то отношение к большому количеству записей, которые у меня есть в таблице истории цен (3.5M). Возможно, это поможет, если я добавлю индекс в столбец Price_h.date? –

+2

Кажется, что этот запрос занимает примерно такое же количество времени независимо от того, сколько результатов оно возвращает, тогда как запрос a1ex07 занимает больше времени с увеличением результатов, как и следовало ожидать. Я просто немного удивился тому, как медленно это происходит для небольших наборов результатов и насколько быстро решение a1ex07 для одного и того же небольшого набора результатов. Поскольку в «Реальном мире» я буду работать с довольно большими результирующими наборами, я выбрал это как ответ. –

3

Попробуйте это:

SELECT Product.UPC, Product.Name, Price_h.Price, MAX(Price_h.Date) 
FROM Product 
INNER JOIN Price_h 
    ON Product.Id = Price_h.Product_id 
GROUP BY Product.UPC, Product.Name, Price_h.Price 
+1

Это было бы работать, но это Wouldnt дать ему правильную историю цен ry, который соответствует max (date) ... – Ariel

+0

Этот запрос возвращает Max (date) для каждого (Product.UPC + Product.Name + Price_h.Price). Это не последняя цена продукта. – a1ex07

+1

Ариэль и a1ex07 верны. Этот запрос действительно возвращает правильную дату, но не правильную цену. –

3
SELECT Product.UPC, Product.Name, Price_h.Price, Price_h.Date 
FROM Product 
LEFT JOIN Price_h 
ON (Product.Id = Price_h.Product_id AND Price_h.Date = 
    (SELECT MAX(Date) FROM Price_h ph1 WHERE ph1.Product_id = Product.Id)); 
+0

+1: Хотя он не является поклонником коррелированного подзапроса на JOIN –

0
SELECT n.product_id, 
     n.product_name, 
     n.product_articul, 
     n.product_price, 
     n.product_discount, 
     n.product_description, 
     n.product_care, 
     (SELECT photo_name FROM siamm_product_photos WHERE product_id = n.product_id LIMIT 1) AS photo_name 
FROM siamm_product as n; 
0

Почему бы не держать его просто и быстро:

SELECT 
Product.UPC, Product.Name, Price_h.Price, Price_h.Date 
FROM 
Product 
LEFT JOIN 
Price_h 
ON Product.Id = Price_h.Product_id; 
ORDER BY 
Price_h.Date DESC 
LIMIT 1