2013-04-14 149 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和额外的连接。这取决于你的数据结构。