2010-06-21 18 views
14

J'ai deux tables MySQL (produit et l'historique des prix) que je voudrais rejoindre:Comment faire un "distinct" se joindre à MySQL

Product Table:

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

Price_h table:

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

Je peux effectuer simple 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; 

Mais comme prévu si j'ai plus d'une entrée pour un produit dans l'historique des prix, j'obtiens un résultat pour chaque prix historique.

Comment une structure peut-elle structurer une jointure qui ne renvoie qu'une seule occurrence de chaque produit avec uniquement l'entrée la plus récente de la table d'historique des prix qui lui est associée?

Répondre

19

Utilisation:

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: Il devrait être plus rapide que le mien. Bien que plus de code. – a1ex07

+0

Je comprends pourquoi vous dites que cela devrait être plus rapide, mais je n'ai pas encore trouvé de situation où cela soit. Je pense que cela peut avoir quelque chose à voir avec le grand nombre d'enregistrements que j'ai dans le tableau d'historique des prix (3.5M). Peut-être que cela aiderait si j'ajoutais un index à la colonne Price_h.date? –

+2

Il semble que cette requête prenne approximativement le même laps de temps, peu importe le nombre de résultats qu'elle renvoie, tandis que la requête de a1ex07 prend plus de temps avec des résultats accrus, comme on pouvait s'y attendre. J'étais juste un peu surpris de voir à quel point c'est lent pour de petits ensembles de résultats et à quelle vitesse la solution d'a1ex07 est pour le même petit jeu de résultats. Puisque dans le "monde réel" je vais travailler avec des ensembles de résultats assez volumineux, j'ai choisi cela comme réponse. –

3

Essayez ceci:

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

Cela travaillerait, mais elle ne tenait pas donnez-lui l'historique des prix correct ent ry qui correspond à la valeur max (date) ... – Ariel

+0

Cette requête renvoie Max (date) pour chaque (Product.UPC + Product.Name + Price_h.Price). Ce n'est pas le dernier prix pour le produit. – a1ex07

+1

Ariel et a1ex07 sont corrects. Cette requête parvient à renvoyer la date correcte, mais pas le prix correct. –

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: Bien que n'étant pas un fan de la sous-requête corrélée sur le 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

Pourquoi ne pas rester simple et rapide:

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