我正在尝试构建一种密集等级的功能,但不完全是密集等级。我想对每个组进行排名,但是在每个组中,我想对相同的值保持相同的排名。我编写了以下查询,它为我提供了一种密集等级的功能
SELECT id, item_code
@curRank := @curRank + 1 AS rank
FROM table t, (SELECT @curRank := 0) r
WHERE <several filters>
我想要这个
我找到的最接近的问题是这个MySQL give a rank to each group
请帮助。
答案 0 :(得分:2)
使用变量的正确方法是:
SELECT id,item_code,
(@rn := if(@id = id,
if(@ic = item_code, @rn, -- do not increment
if(@ic := item_code, @rn + 1, @rn + 1)
),
if(@id := id,
if(@ic := @item_code, 1, 1
), 1
if(@ic := @item_code, 1, 1
)
)
)
) as dense_rank
FROM table t CROSS JOIN
(SELECT @rn := 0, @id := '', @ic := '') params
WHERE <several filters>
ORDER BY item_code;
两件事:
ORDER BY
非常重要。您还可以使用相关子查询来表达这一点:
SELECT id, item_code
(SELECT COUNT(DISTINCT item_code)
FROM table t2
WHERE . . . AND
t2.item_code <= t.item_code
) as rank
FROM table t
WHERE <several filters>
答案 1 :(得分:2)
您可以在复合PRIMARY KEY中使用AUTO_INCREMENT rank
列创建(临时) MyISAM 表。这样,当您使用不同的rank
组合填充表格时,ID
每(id, item_code)
将有一个序列。然后,您可以将该表与原始数据连接起来。
CREATE TEMPORARY TABLE tmp_rank(
id INT,
item_code varchar(50),
rank INT AUTO_INCREMENT,
PRIMARY KEY (id, rank)
) engine=MyISAM
SELECT DISTINCT NULL as rank, id, item_code
FROM test t
-- WHERE <several filters>
ORDER BY id, item_code
;
SELECT t.*, x.rank
FROM tmp_rank x
JOIN test t USING(id, item_code)
-- WHERE <several filters>
如果要在单个查询中进行查询,可以尝试以下操作:
SELECT id, item_code,
CASE
WHEN id = @curId AND item_code = @curCode
THEN @curRank
WHEN id <> @curId THEN @curRank := 1
ELSE @curRank := @curRank + 1
END AS rank,
@curId := id,
@curCode := item_code
FROM test t
CROSS JOIN (SELECT
@curRank := 0,
cast(@curCode := null as signed),
cast(@curId := NULL as char)
) r
#WHERE <several filters>
ORDER BY id, item_code
请注意,未定义SQL语句中操作的评估顺序。因此,当您在同一条语句中读取和写入用户变量时,您将继续介绍实现细节。
在 MySQL 8 或 MariaDB 10.2 中,它将是:
SELECT id, item_code,
DENSE_RANK() OVER (PARTITION BY id ORDER BY item_code) as `rank`
FROM test t
-- WHERE <several filters>
答案 2 :(得分:1)
仅当@cur_rank
更改时,才需要递增item_code
,而当1
更改时,则将其重新设置为id
。
SELECT id, item_code,
@curRank := IF(@curId = id,
IF(@curItem = item_code, @curRank, @curRank + 1),
1) AS rank,
@curId := id, @curItem := item_code
FROM table t, (SELECT @curRank := 0, @curId := 0, @curItem := null) r
WHERE <several filters>
ORDER BY id, item_code