一个表中有多个等级

我需要以下,任何人都可以请帮我做到这一点。

Rank Cust_Type Cust_Name Revenue 1 Top A 10000 2 Top B 9000 3 Top C 8000 1 Bottom X 5000 2 Bottom Y 6000 3 Bottom Z 7000 

我需要单独的排名顶部和底部Cust_Type,这一切都在MySQL中。

这有点棘手。 您可能想要使用variables,如下例所示:

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

(SELECT @curRow := 0, @curType := '') r部分允许variables初始化,而不需要单独的SET命令。

testing用例:

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

结果:

 +------+-----------+-----------+---------+ | rank | cust_type | cust_name | revenue | +------+-----------+-----------+---------+ | 1 | Top | A | 10000 | | 2 | Top | B | 9000 | | 3 | Top | C | 8000 | | 1 | Bottom | Z | 7000 | | 2 | Bottom | Y | 6000 | | 3 | Bottom | X | 5000 | +------+-----------+-----------+---------+ 6 rows in set (0.00 sec) 

另一个testing案例:

 CREATE TABLE sales (cust_type varchar(10), cust_name varchar(10), revenue int); INSERT INTO sales VALUES ('Type X', 'A', 7000); INSERT INTO sales VALUES ('Type X', 'B', 8000); INSERT INTO sales VALUES ('Type Y', 'C', 5000); INSERT INTO sales VALUES ('Type Y', 'D', 6000); INSERT INTO sales VALUES ('Type Y', 'E', 4000); INSERT INTO sales VALUES ('Type Z', 'F', 4000); INSERT INTO sales VALUES ('Type Z', 'G', 3000); 

结果:

 +------+-----------+-----------+---------+ | rank | cust_type | cust_name | revenue | +------+-----------+-----------+---------+ | 1 | Type Z | F | 4000 | | 2 | Type Z | G | 3000 | | 1 | Type Y | D | 6000 | | 2 | Type Y | C | 5000 | | 3 | Type Y | E | 4000 | | 1 | Type X | B | 8000 | | 2 | Type X | A | 7000 | +------+-----------+-----------+---------+ 7 rows in set (0.00 sec) 

你显然可以按升序而不是降序来对cust_type进行sorting。 我使用降序只是在原始testing用例中有Top Bottom

我发现使用CASE@curRow@curType的解决scheme存在问题。 这取决于MySQL用来处理查询的执行计划。 例如,如果向查询添加连接,则会显示。 那么不能保证排名将被正确计算。

对答案稍作修改:

 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); 

如果我只查询sales表,我得到正确的顺序排名,但如果我joincust_type表的排名值不再是正确的

 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; 

结果:

 +------+-----------+-----------+---------+ | 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正在将初始查询运行到临时表中,然后在已经计算了sorting之后, ORDER BY正在对临时表执行。

这与托马斯的答案类似,但稍微简单一点:

 SELECT (SELECT COUNT(Cust_Type) FROM sales WHERE Cust_Type = S.Cust_Type AND Revenue >= S.Revenue) AS Rank, Cust_Type, Cust_Name, Revenue FROM sales AS S ORDER BY Cust_Type DESC, Rank; 

我不确定性能如何与Daniel的解决scheme相比较,特别是在非常大的数据集上,或者如果您必须使用复杂的联接。

什么是不清楚的是项目应该如何排名(我认为是由收入),或者你是否只拉了一定数量的价值(如前3名​​和下3名),所以我假设你想要所有的价值观。 鉴于这些假设,

 Select Cust_Name, Cust_Type , (Select Count(*) From Table As T1 Where T1.Revenue > T.Revenue ) + 1 As Rank From Table As T Where Cust_Type = 'Top' Union All Select Cust_Name, Cust_Type , (Select Count(*) From Table As T1 Where T1.Revenue < T.Revenue ) + 1 As Rank From Table As T Where Cust_Type = 'Bottom' 

如果您尝试在单个非工会查询中执行此操作,则可以执行以下操作:

 Select Cust_Name, Cust_Type , Case Z.Cust_Type When 'Top' Then Z.TopRank Else Z.BottomRank End As Rank From ( Select Cust_Name, Cust_Type , (Select Count(*) From Table As T1 Where T1.Revenue > T.Revenue ) + 1 As TopRank , (Select Count(*) From Table As T1 Where T1.Revenue < T.Revenue ) + 1 As BottomRank From Table As T ) As Z