我需要满足以下条件,任何人都可以请帮我做。多个等级
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中。
我需要满足以下条件,任何人都可以请帮我做。多个等级
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中。
这是一个有点棘手。你可能想使用变量,如在下面的例子:
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
部分允许变量初始化,而不需要单独SET
命令。
测试用例:
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)
另一测试情况:
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
。我用降只是在原有的测试案例Bottom
之前有Top
。
非常好的解决方案。我希望MySQL团队能够提供窗口和分析功能来避免这些变通方法。 – Shiva 2012-02-01 03:56:41
我不明白为什么上述不起作用,当我使用\ @curRow:= 0 AND \ @curType:= cust_type而不是这里使用的:= 1。 – mathieu 2012-06-19 08:14:03
我刚刚尝试使用此解决方案,并注意到一些奇怪的事情。我只是想看看每个组的最高值,所以我在查询结尾添加了'rank = 1'。它显示了正确的行,但排列的列都是2.如果我只是使用没有HAVING子句的查询,它可以正常工作(从rank = 1开始每个组)。万一它很重要,而不是使用一个表我使用的是一个视图,ORDER BY条件是在视图定义。 – Barmar 2012-10-03 20:13:12
什么是不完全清楚的是该项目应如何进行排名(我假定按收入),还是你只是拉一定数量值(例如顶部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
我发现与解决的问题使用CASE
,@curRow
和@curType
。这取决于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
表我得到正确的顺序排名,但如果我加入到cust_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为r unning初始查询到一个临时表,然后将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;
我不知道如何表现比较给丹尼尔的解决方案,尤其是在非常大的数据集,或者如果你有使用复杂的连接。
这对我来说通过保持销售收入和订单分开排列。
SELECT
(Select count(s1.revenue)+1 from sales s1 where s.cust_type_id = s1.cust_type_id and s1.revenue > s.revenue)
As rank,
t.type_name,
s.cust_name,
s.revenue
FROM sales s LEFT JOIN
cust_type t USING(cust_type_id)
Group by t.type_name,s.cust_name,s.revenue DESC order by s.revenue DESC;
您是否在问如何创建此表? 如何查询此表的某些内容? 如何查询另一个表以获得像这样的结果? – grossvogel 2010-07-01 23:45:48
请根据您收到的答案使用评论功能进行说明。如果某些内容不适合评论,则应该将其编辑到您的问题中(请参阅编辑链接) – 2011-09-21 20:41:01