[英]How to use rank() over PARTITION BY in Mysql
Let's consider that there are three material types such as ('COTTON', 'LEATHER', 'SILK') and I want to fetch the dress_id's which has all theses three material types.让我们考虑一下有三种材料类型,例如 ('COTTON', 'LEATHER', 'SILK'),我想获取具有所有这三种材料类型的dress_id。 I want to rank them as well.
我也想给他们排名。
Can someone explain step by step on how to do this ?有人可以逐步解释如何做到这一点吗? I came through few examples and none of them seems to be clear to me.
我遇到了几个例子,但对我来说似乎没有一个是清楚的。
The output should look something like
DRESS_ID MATERIAL LAST_UPDATED_DATE RANK
111 COTTON 2019-08-29 1
111 SILK 2019-08-30 2
111 LEATHER 2019-08-31 3
222 COTTON 2019-08-29 1
222 SILK 2019-08-30 2
222 LEATHER 2019-08-31 3
222 LEATHER 2019-09-02 4
I get an error in MYSQL work bench while executing this query.执行此查询时,我在 MYSQL 工作台中收到错误消息。 Error Code: 1305. FUNCTION rank does not exist.
错误代码:1305。FUNCTION 等级不存在。
SELECT dress_id,
rank() over(PARTITION BY dress_id, material ORDER by LAST_UPDATED_DATE asc) as rank
FROM dress_types;
In earlier versions of MySQL, you can either use variables or a correlated subquery.在早期版本的 MySQL 中,您可以使用变量或相关子查询。
Because you have only a handful of materials for each dress, a correlated subquery is reasonable, particularly with the right index.因为每件衣服只有少量材料,所以相关子查询是合理的,特别是使用正确的索引。 The code looks like:
代码如下:
SELECT d.dress_id, d.material,
(SELECT COUNT(*)
FROM dress_types d2
WHERE d2.dress_id = d.dress_id AND
d2.last_updated_date <= d.last_updated_date
) as rank
FROM dress_types d;
Note that this implements the logic based on your data not the query.请注意,这实现了基于您的数据而不是查询的逻辑。 The corresponding query would be:
相应的查询将是:
SELECT dress_id,
rank() over (PARTITION BY dress_id ORDER by LAST_UPDATED_DATE asc) as rank
FROM dress_types;
The index that you want is on dress_types(dress_id, last_updated_date)
.您想要的索引位于
dress_types(dress_id, last_updated_date)
。
Actually, these are the same so long as there are no duplicates (by date).实际上,只要没有重复项(按日期),这些就是相同的。 The logic may be different if there are duplicates.
如果有重复,逻辑可能会有所不同。
SELECT dress_id
, material
, LAST_UPDATED_DATE
rank() over(PARTITION BY dress_id ORDER by LAST_UPDATED_DATE asc) as rank
FROM dress_types
SELECT T.*,
CASE WHEN @prev_dress_id != T.dress_id THEN @rank:=1
ELSE @rank:=@rank+1
END as rank,
@prev_dress_id := T.dress_id as set_prev_dress_id
FROM
(SELECT dress_id,material,last_updated_date
FROM dress_types T1
WHERE EXISTS (SELECT 1 FROM dress_types E1 WHERE E1.dress_id = T1.dress_ID AND E1.material = 'COTTON')
AND EXISTS (SELECT 1 FROM dress_types E2 WHERE E2.dress_id = T1.dress_ID AND E2.material = 'SILK')
AND EXISTS (SELECT 1 FROM dress_types E3 WHERE E3.dress_id = T1.dress_ID AND E3.material = 'LEATHER')
ORDER BY dress_id asc,last_updated_date asc
)T,(SELECT @prev_dress_id:=-1)V
The inner select selects dresses that have existence of all 3 materials and ordered by dress_id, last_updated_date.内部选择选择所有 3 个材料都存在并按dress_id、last_updated_date 排序的连衣裙。 The outer joins it with a prev_dress_id variable that can be set at the end of each row.
外部将它与一个 prev_dress_id 变量连接起来,该变量可以在每行的末尾设置。 The the logics in case statement to calculate rank based on @prev_dress_id != or = T.dress_id.
case语句根据@prev_dress_id != or = T.dress_id计算排名的逻辑。 sqlfiddle
sqlfiddle
For previous versions of MySQL 8.0 you must use variables to simulate the ranking:对于以前版本的 MySQL 8.0,您必须使用变量来模拟排名:
SET @rownum := 0;
SET @group_number := 0;
SELECT dress_id, material, last_updated_date, rank FROM (
SELECT @rownum := case
when @group_number = dress_id then @rownum + 1
else 1
end AS rank, dress_id, material, last_updated_date,
@group_number := dress_id
FROM dress_types
ORDER BY
dress_id,
FIELD(material, 'COTTON', 'SILK', 'LEATHER'),
last_updated_date
) t
See the demo .请参阅演示。
Results:结果:
| dress_id | material | last_updated_date | rank |
| -------- | -------- | ------------------- | ---- |
| 111 | COTTON | 2019-08-29 00:00:00 | 1 |
| 111 | SILK | 2019-08-30 00:00:00 | 2 |
| 111 | LEATHER | 2019-08-31 00:00:00 | 3 |
| 222 | COTTON | 2019-08-29 00:00:00 | 1 |
| 222 | SILK | 2019-08-30 00:00:00 | 2 |
| 222 | LEATHER | 2019-08-31 00:00:00 | 3 |
| 222 | LEATHER | 2019-09-02 00:00:00 | 4 |
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.