2010-06-21 14 views
14

Mam dwie tabele MySQL (produkt i historia cena), że chciałabym dołączyć:Jak zrobić "odrębny" join z MySQL

Product tabela:

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

Price_h tabela:

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

mogę wykonać proste 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; 

Ale zgodnie z oczekiwaniami, jeśli mam więcej niż jeden wpis dla produktu w tabeli historii cen, otrzymuję jeden wynik dla każdej ceny historycznej.

W jaki sposób struktura może zostać sprzężona, która zwróci tylko jedną instancję każdego produktu z dołączonym do niej tylko najnowszym wpisem z tabeli historii cen?

Odpowiedz

19

Zastosowanie:

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: Powinien być szybszy niż mój. Chociaż dłuższy kod. – a1ex07

+0

Rozumiem, dlaczego mówisz, że powinno być szybciej, ale muszę jeszcze znaleźć taką okoliczność, w której jest. Myślę, że może to mieć coś wspólnego z dużą liczbą rekordów, które mam w tabeli historii cen (3,5M). Być może byłoby pomocne, jeśli dodałem indeks do kolumny Price_h.date? –

+2

Wygląda na to, że zapytanie to zajmuje mniej więcej tyle samo czasu, niezależnie od tego, ile wyników zwraca, podczas gdy kwerenda a1ex07 trwa dłużej ze zwiększonymi wynikami, jak można się było spodziewać. Byłem tylko trochę zaskoczony tym, jak powolne jest to dla małych zestawów wyników i jak szybkie jest rozwiązanie a1ex07 dla tego samego małego zestawu wyników. Ponieważ w "rzeczywistym świecie" będę pracował z raczej dużymi zestawami wyników, które wybrałem jako odpowiedź. –

3

Spróbuj tego:

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

Że działa, ale to nie byłby podaj mu prawidłową historię cen ry, który odpowiada z max (data) ... – Ariel

+0

Ta kwerenda zwraca Max (data) dla każdego (Product.UPC + Product.Name + Price_h.Price). To nie jest najnowsza cena za produkt. – a1ex07

+1

Ariel i a1ex07 są poprawne. W tym zapytaniu udaje się zwrócić poprawną datę, ale nieprawidłowa cena. –

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: Chociaż nie jest fanem skorelowanego podzapytania na 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

Dlaczego nie zachować to prosty i szybki:

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