SQL MIN()&通过...分组

时间:2013-04-14 19:56:20

标签: mysql group-by min

我正在寻找一个更优雅的解决方案,解决我在使用与GROUP BY一起使用的MySQL MIN()时遇到的问题。

我有两张桌子:

  1. 产品(id,group_id)
  2. product_attributes(product_id,attribute_id,value)
  3. 我希望从某个产品组中选择每个金属组中最便宜的金属(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;
    

2 个答案:

答案 0 :(得分: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

这是有效的,假设每product_id有一个metal.value。如果有多个此类产品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和其他联接。这取决于数据的结构。

答案 1 :(得分: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