2013-04-14 201 views
0

我正在尋找一種更優雅的解決方案,以解決與MySQL MIN()與GROUP BY一起使用時遇到的問題。SQL MIN()&GROUP BY

我有兩個表:

  1. 產品(ID,GROUP_ID)
  2. product_attributes(產品,attribute_id,值)

我希望選擇最便宜的金屬從各金屬組(attribute_id = 40)來自某個產品組。

下面的查詢可以工作,但我很肯定它可以寫得更好。

SELECT metal.product_id, metal.value AS `metal`, `price`.value AS `price` 
FROM 
    product_attributes metal 
INNER JOIN 
    (
     SELECT metal.value AS `metal`, MIN(price.value) AS `price` 
     FROM 
      product_attributes metal 
     LEFT JOIN 
      product_attributes price 
     ON metal.product_id = price.product_id 
     INNER JOIN products p 
     ON p.id = metal.product_id 
     WHERE 
      metal.attribute_id = 40 AND 
      price.attribute_id = 37 AND 
      p.group_id = 1 
     GROUP BY 
      metal.value 
     ORDER BY metal ASC, price DESC 
    ) AS d ON 
    d.metal = metal.value 
LEFT JOIN 
    product_attributes price ON 
    metal.product_id = price.product_id AND price.attribute_id = 37 
INNER JOIN 
    products p ON 
    p.id = metal.product_id 
WHERE 
    metal.attribute_id = 40 
    AND d.price = price.value 
    AND p.group_id = 1 
GROUP BY 
    metal.value 
ORDER BY 
    metal.value ASC, 
    price.value DESC; 

回答

0

解決方案終於比我簡單了。 我已經在內部查詢中按價格排序了我的數據,因此在GROUP BY之前強制排序,這樣我就能得到我需要的(每個金屬組中最便宜的產品)。

SELECT * FROM 
      (
       SELECT metal.enum_id AS `metal`, metal.product_id FROM product_attributes metal 
       LEFT JOIN product_attributes price ON metal.product_id = price.product_id AND price.attribute_id = 37 
       INNER JOIN products p ON p.id = metal.product_id 
       WHERE 
        metal.attribute_id = 40 AND 
        p.group_id = 1 AND 
        p.id NOT IN (SELECT DISTINCT product_id FROM product_attributes WHERE (attribute_id=162 OR attribute_id=204 OR attribute_id=205) AND `value`=1) 
       ORDER BY price.value+'0' ASC 
      ) AS s 
      GROUP BY metal 
0

我想你可以只寫這個作爲group by聲明:

SELECT metal.value AS `metal`, metal.product_id, MIN(price.value) AS `price` 
    FROM product_attributes metal LEFT JOIN 
     product_attributes price 
     ON metal.product_id = price.product_id 
     INNER JOIN products p 
     ON p.id = metal.product_id 
    WHERE metal.attribute_id = 40 AND 
     price.attribute_id = 37 AND 
     p.group_id = 1 
    GROUP BY metal 
    order by metal, price 

這工作,假設有每一個metal.valueproduct_id。如果有多個這樣的產品ID,那麼你就需要加入早在屬性表:

SELECT metal.product_id, metal.value AS `metal`, d.`price` 
FROM (SELECT metal.value AS `metal`, MIN(price.value) AS `price` 
     FROM product_attributes metal LEFT JOIN 
      product_attributes price 
      ON metal.product_id = price.product_id 
      INNER JOIN products p 
      ON p.id = metal.product_id 
     WHERE metal.attribute_id = 40 AND 
      price.attribute_id = 37 AND 
      p.group_id = 1 
     GROUP BY metal 
    ) d join 
    product_attributes metal 
    ON d.metal = metal.value 
ORDER BY metal.value ASC, d.price DESC 

這是可能的,你可能還需要where和額外的連接。這取決於你的數據結構。