Multiple Ranks in one table

前端 未结 6 973
庸人自扰
庸人自扰 2020-11-27 22:00

I need the following, Can anyone please help me do it.

Rank   Cust_Type   Cust_Name   Revenue
1      Top         A           10000
2      Top         B               


        
6条回答
  •  被撕碎了的回忆
    2020-11-27 22:25

    I found a problem with the solution using CASE, @curRow, and @curType. It depends on the execution plan MySQL uses to process the query. For example, it shows up if you add a join to the query. Then there is no guarantee that the rank is going to be computed correctly.

    Making a slight change to the answer:

    CREATE TABLE sales (cust_type_id int, cust_name varchar(10), revenue int);
    CREATE TABLE cust_type (cust_type_id int, type_name varchar(10));
    
    INSERT INTO cust_type VALUES (1, 'Bottom');
    INSERT INTO cust_type VALUES (2, 'Top');
    
    INSERT INTO sales VALUES (2, 'A', 10000);
    INSERT INTO sales VALUES (2, 'B', 9000);
    INSERT INTO sales VALUES (2, 'C', 8000);
    INSERT INTO sales VALUES (1, 'X', 5000);
    INSERT INTO sales VALUES (1, 'Y', 6000);
    INSERT INTO sales VALUES (1, 'Z', 7000);
    

    If I query only the sales table I get the rank in the correct order, but if I join to the cust_type table the rank values are no longer correct

    SELECT    ( 
                CASE s.cust_type_id 
                WHEN @curType 
                THEN @curRow := @curRow + 1 
                ELSE @curRow := 1 AND @curType := s.cust_type_id END
              ) AS rank,
              t.type_name,
              s.cust_name,
              s.revenue
    FROM      sales s,
              cust_type t,
              (SELECT @curRow := 0, @curType := 0) r
    WHERE s.cust_type_id = t.cust_type_id 
    ORDER BY  t.type_name DESC, s.revenue DESC;
    

    Result:

    +------+-----------+-----------+---------+
    | rank | type_name | cust_name | revenue |
    +------+-----------+-----------+---------+
    |    1 | Top       | A         |   10000 |
    |    2 | Top       | B         |    9000 |
    |    3 | Top       | C         |    8000 |
    |    3 | Bottom    | Z         |    7000 |
    |    2 | Bottom    | Y         |    6000 |
    |    1 | Bottom    | X         |    5000 |
    +------+-----------+-----------+---------+
    

    MySQL is running the initial query into a temp table and then the ORDER BY is executing against the temp table after a rank was already computed.

提交回复
热议问题