【问题标题】:SQL MIN() & GROUP BYSQL MIN() 和 GROUP BY
【发布时间】:2013-04-06 21:18:09
【问题描述】:

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

我有两张桌子:

  1. 产品(id、group_id)
  2. product_attributes(product_id、attribute_id、value)

我希望从某个产品组的每个金属组(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;

【问题讨论】:

    标签: mysql group-by min


    【解决方案1】:

    解决方案终于比我简单了。 我在内部查询中按价格对数据进行了排序,因此在 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
    

    【讨论】:

      【解决方案2】:

      我认为您可以将其写为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.value 有一个product_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 和其他连接。这取决于您的数据结构。

      【讨论】:

        猜你喜欢
        • 2012-07-25
        • 2012-07-25
        • 2018-10-26
        • 2020-07-23
        • 2010-10-17
        • 1970-01-01
        • 1970-01-01
        • 2021-05-03
        • 2021-03-14
        相关资源
        最近更新 更多