我有一个表格items
,其中列出了id
,popularity
和rank
列中的不同元素。
popularity
列包含一个int
,可以按流行度对元素进行排序。
我已经查询了按受欢迎程度排序并为每个条目设置了排名:
SELECT id,
@curRank := @curRank + 1 AS rank
FROM items, (SELECT @curRank := 0) r
ORDER BY popularity DESC
此查询运行良好,并给我一个id
和rank
的结果,其中rank
的值符合预期,并按popularity
的顺序排列。
我想要实现的是为每个条目设置rank
的值,我以此方式进行了尝试:
UPDATE items A
JOIN (
SELECT id,
@curRank := @curRank + 1 AS rank
FROM items,
(SELECT @curRank := 0) r
ORDER BY popularity DESC
) AS ranks
SET A.rank = ranks.rank
WHERE A.id = ranks.id
为每行设置一个rank
值,但不遵守ORDER BY popularity DESC
。相反,排名值似乎是由id
顺序设置的(id
1具有rank
1,id
2具有rank
2等)。 / p>
我在做什么错了?
此致
答案 0 :(得分:3)
我认为您正在使这项工作变得比应做的要困难。
SET @curRank = 0;
UPDATE items
SET rank = (@curRank := @curRank+1)
ORDER BY popularity DESC;
我只是在UPDATE之前在SET语句中设置@curRank
变量。当您尝试将它们组合在一起时,它只会使您的代码阅读者想知道这意味着什么。
您无需使它们成为同一语句的一部分。只要您在同一数据库会话中执行两个语句,会话变量将保持其值。
不需要子查询或联接。只需使用UPDATE ... ORDER BY(尽管如果确实需要执行JOIN操作,则在MySQL中无法使用ORDER BY进行UPDATE)。
答案 1 :(得分:1)
MySQL在处理变量和排序时具有令人惊讶的行为。
您可以 尝试的一件事是更早地进行订购,方法是将ORDER BY
上的items
移至子查询,如下所示:
UPDATE items A
JOIN (
SELECT id,
@curRank := @curRank + 1 AS rank
FROM
(SELECT id FROM items ORDER BY popularity DESC) items,
(SELECT @curRank := 0) r
) AS ranks
SET A.rank = ranks.rank
WHERE A.id = ranks.id
数据:
| id | popularity | rank |
| --- | ---------- | ---- |
| 1 | 1 | 1 |
| 2 | 2 | 2 |
| 3 | 3 | 3 |
| 4 | 4 | 4 |
| 5 | 5 | 5 |
更新后:
| id | popularity | rank |
| --- | ---------- | ---- |
| 1 | 1 | 5 |
| 2 | 2 | 4 |
| 3 | 3 | 3 |
| 4 | 4 | 2 |
| 5 | 5 | 1 |