【问题标题】:Select multiple maximum values选择多个最大值
【发布时间】:2011-04-05 04:01:51
【问题描述】:

我有一个名为order 的表,其中包含iduser_idpriceitem_id 列。商品价格不固定,我想选择每件商品最贵的订单。我想在同一个查询中选择user_iditem_idprice。我尝试了以下查询,但它没有返回正确的结果集。

SELECT user_id, item_id, MAX(price)
FROM order
GROUP BY item_id

此查询返回的某些行有错误的user_id。但是,结果集中的所有行都显示每个项目的正确最高价格。

【问题讨论】:

    标签: mysql select group-by max


    【解决方案1】:

    如果你想从订单中获得前 2 名,试试这个...

    如果您想要前 3 名,那么只需更改最后一个条件 其中item_rank in (1,2) ;where item_rank in (1,2,3) ;

    select * from 
        (select  item_id  , price
        , @curRow % @curNval  as item_rank
        ,  @curRow := @curRow + 1 AS row_number
        from `order` ,   (SELECT @curRow := 1 , @curNval := 3 ) r  
        order by  item_id , price desc  ) tab  where item_rank in (1,2) ;
    

    【讨论】:

    • 可以用作 item_rank > 2 或 item_rank > n
    【解决方案2】:

    也许这有点长,但你会获得可读性

    SELECT
            *
    FROM
        `order`
    JOIN
        (
            SELECT 
                item_id, 
                MAX(price) price 
            FROM 
                `order` 
            GROUP BY 
                item_id
        ) 
        USING(item_id, price);
    

    【讨论】:

      【解决方案3】:
      SELECT user_id, item_id, MAX(price) 
      FROM order
      GROUP BY item_id
      

      您使用的 SQL 与 GROUP 相矛盾。 一旦你使用了 GROUP,MYSQL 总是会选择 FIRST user_id,但价格最高,这就是用户错误但价格正确的原因。

      您可以尝试添加ORDER BY price DESC 看看会发生什么,但我没有在我的环境中尝试。

      【讨论】:

        【解决方案4】:

        这是每组最多的问题。这个常见问题有various approaches。在 MySQL 上,使用 null-self-join 通常比任何涉及子查询的方法更快、更简单:

        SELECT o0.user_id, o0.item_id, o0.price
        FROM order AS o0
        LEFT JOIN order AS o1 ON o1.item_id=o0.item_id AND o1.price>o0.price
        WHERE o1.user_id IS NULL
        

        即。 “选择价格较高的同一商品没有其他行的每一行”。

        (如果两行具有相同的最高价格,您将同时返回。在平局的情况下究竟该怎么做是每组最大解决方案的一般问题。)

        【讨论】:

        • the link you provided 中的基准不是显示派生表(不相关子查询)方法比 null-self-join 快得多吗? ...我也曾经认为 null-self-join 在 MySQL 中稍微快一些,事实上我对这些基准感到非常惊讶。我有一种感觉我要自己做一些测试:) ... +1 反正
        • 是的,结果当然会根据所涉及的表和索引的大小而有所不同。在过去,我通常发现空自连接在我的特定数据集上最快,使用 MySQL(已知其子查询支持相对较新,因此可能没有尽可能优化)。使用最新版本的 MySQL 进行更多调查会很有趣。
        【解决方案5】:

        您需要按 item_id 和 user_id 进行分组(显示每个用户每件商品的最高价格),或者如果您只想要组中的商品,则需要重新考虑 user_id 列。 例如显示商品的最高价格并显示最后更改价格的用户,或者显示商品的最高价格并显示为商品设置最高价格的用户等。查看this post 了解这样做的一些模式。

        【讨论】:

        • 我无法在一次查询中获得该商品、其最高价格以及给出该价格的用户吗?
        【解决方案6】:

        您可能希望使用派生表,如下所示:

        SELECT    o1.item_id, o1.max_price, o2.user_id user_of_max_price
        FROM      (
                     SELECT item_id, MAX(price) max_price
                     FROM `order`
                     GROUP BY item_id
                  ) o1
        JOIN      `order` o2 ON (o2.price = o1.max_price AND o2.item_id = o1.item_id)
        GROUP BY  o1.item_id;
        

        测试用例:

        CREATE TABLE `order` (user_id int, item_id int, price decimal(5,2));
        
        INSERT INTO `order` VALUES (1, 1, 10);
        INSERT INTO `order` VALUES (1, 2, 15);
        INSERT INTO `order` VALUES (1, 3, 8);
        INSERT INTO `order` VALUES (2, 1, 20);
        INSERT INTO `order` VALUES (2, 2, 6);
        INSERT INTO `order` VALUES (2, 3, 15);
        INSERT INTO `order` VALUES (3, 1, 18);
        INSERT INTO `order` VALUES (3, 2, 13);
        INSERT INTO `order` VALUES (3, 3, 10);
        

        结果:

        +---------+-----------+-------------------+
        | item_id | max_price | user_of_max_price |
        +---------+-----------+-------------------+
        |       1 |     20.00 |                 2 |
        |       2 |     15.00 |                 1 |
        |       3 |     15.00 |                 2 |
        +---------+-----------+-------------------+
        3 rows in set (0.00 sec)
        

        【讨论】:

          【解决方案7】:

          您需要首先获取每个商品 ID 的最高价格,然后返回到 order 以获取以最高价格订购商品的记录。类似以下查询的内容应该可以工作。虽然,它会返回所有具有最高商品价格的记录。

          SELECT user_id, item_id, price
          FROM order o
          JOIN (
                  SELECT item_id, max(price) max_price
                  FROM order
                  GROUP BY item_id
               ) o2 
            ON o.item_id = o2.item_id AND o.price = o2.max_price;
          

          【讨论】:

            【解决方案8】:

            您的查询按item_id 对行进行分组。如果您有多个item_id 1 的项目,不同的user_id,它只会选择第一个user_id,而不是最高价格的user_id

            【讨论】:

            • 是的,没错。那么我该如何实现我想要在这里做的事情呢?我试图找出谁以最优惠的价格购买了该商品以及该价格是多少。
            猜你喜欢
            • 2021-09-28
            • 2022-09-23
            • 1970-01-01
            • 1970-01-01
            • 2020-05-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多