【问题标题】:Rank order grouped data in MySQL without session variables?在没有会话变量的情况下对 MySQL 中的分组数据进行排序?
【发布时间】:2018-11-21 01:38:02
【问题描述】:

我的数据如下所示:

Table Name = sales_orders

Customer_id| Order_id| Item_Id
-------------------------------
1          | 1      | 10
1          | 1      | 24
1          | 1      | 37
1          | 2      | 11
1          | 2      | 15
1          | 3      | 28
2          | 4      | 37
4          | 6      | 10
2          | 7      | 10

但是,我需要它看起来像这样:

Customer_id| Order_id| Item_Id |Order_rank
------------------------------------------
1          | 1      | 10       |    1   
1          | 1      | 24       |    1
1          | 1      | 37       |    1
1          | 2      | 11       |    2
1          | 2      | 15       |    2
1          | 3      | 28       |    3
2          | 4      | 37       |    1
4          | 6      | 10       |    1
2          | 7      | 10       |    2

Customer_Id 是独一无二的人

Order_id 是唯一的订单

item_id 是产品代码

为了进一步解释,前三行来自客户 #1 的第一个订单 (order_id = 1),此人订购了 3 个不同的商品(10、24 和 37)。然后,他们又购买了另外两种产品的订单 (order_id =2)。 customer_id =2 的人有 2 个唯一订单(4 和 6),而 ID 为“4”的客户有一个唯一订单(order_id =6)

基本上,我需要做的是按 customer_id 和 order Id 对这些订单进行排序,这样我就可以说“Order_id = 7 是 customer_id = 2 的第二个订单,因为 Order_rank = 2”

这里的挑战是我不能在 MySQL 查询中使用会话变量(例如 @grp := customer_id )

例如,不允许这样的查询:

SELECT 
customer_id,
order_id,
@ss := CASE WHEN @grp = customer_id THEN @ss + 1 ELSE 1 END AS 
order_rank,
@grp := customer_id 
FROM 
(
SELECT 
customer_id,
order_id
FROM sales_orders
GROUP BY customer_id, order_id
ORDER BY customer_id, order_id ASC
) AS t_1
CROSS JOIN (SELECT @ss := 0, @grp = NULL)ss

ORDER BY customer_id asc

感谢您的帮助!

【问题讨论】:

    标签: mysql sql session-variables ranking rank


    【解决方案1】:

    在Correlated Subquery 中,我们可以Count(..) 为特定行的customer_id 和order_id 的唯一和先前 order_id 值确定排名。

    我们需要计算唯一值,因为每个订单有多个行(由于多个项目)。


    查询

    SELECT 
      t1.Customer_id, 
      t1.Order_id, 
      t1.Item_Id, 
      (SELECT COUNT(DISTINCT t2.Order_id) 
       FROM sales_orders t2 
       WHERE t2.Customer_id = t1.Customer_id AND 
             t2.Order_id <= t1.Order_id
      ) AS Order_rank 
    FROM sales_orders AS t1;
    

    结果

    | Customer_id | Order_id | Item_Id | Order_rank |
    | ----------- | -------- | ------- | ---------- |
    | 1           | 1        | 10      | 1          |
    | 1           | 1        | 24      | 1          |
    | 1           | 1        | 37      | 1          |
    | 1           | 2        | 11      | 2          |
    | 1           | 2        | 15      | 2          |
    | 1           | 3        | 28      | 3          |
    | 2           | 4        | 37      | 1          |
    | 4           | 6        | 10      | 1          |
    | 2           | 7        | 10      | 2          |
    

    View on DB Fiddle

    【讨论】:

      【解决方案2】:

      您可以使用相关子查询:

      select so.*,
             (select count(*)
              from sales_orders so2
              where so2.Customer_id = so.Customer_id and
                    so2.order_id <= so.order_id
             ) as rank_order
      from sales_orders so;
      

      或者在 MySQL 8+ 中:

      select so.*,
             dense_rank() over (partition by Customer_Id order by Order_Id) as rank_order
      from sales_orders so;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-03-23
        • 2021-04-16
        • 2023-01-30
        • 1970-01-01
        • 1970-01-01
        • 2014-07-28
        • 2020-01-25
        相关资源
        最近更新 更多