Oracle递归子查询因子转换

And*_*rew 5 oracle recursion

我正在尝试使用这种递归SQL功能,但无法让它做我想要的,甚至不能关闭.我在一个展开的循环中编写了逻辑,询问它是否可以转换为单个递归SQL查询,而不是我使用的表更新样式.

http://sqlfiddle.com/#!4/b7217/1

有六名球员排名.他们有id,组ID,分数和排名.

初始状态

+----+--------+-------+--------+
| id | grp_id | score |  rank  |
+----+--------+-------+--------+
| 1  |     1  |  100  | (null) |
| 2  |     1  |   90  | (null) |
| 3  |     1  |   70  | (null) |
| 4  |     2  |   95  | (null) |
| 5  |     2  |   70  | (null) |
| 6  |     2  |   60  | (null) |
+----+--------+-------+--------+
Run Code Online (Sandbox Code Playgroud)

我想把初始得分最高的人给他们排名1.然后我将10点奖励积分给每个拥有相同组ID的人的得分.取下一个最高,分配等级2,分配奖励积分等等,直到没有玩家离开.

用户ID打破了关系.

奖励积分会改变排名.id = 4最初看起来是第二位置95,在领先者后面有100但是有10点奖金,id = 2向上移动并取得现场.

最终状态

+-----+---------+--------+------+
| ID  | GRP_ID  | SCORE  | RANK |
+-----+---------+--------+------+
|  1  |      1  |   100  |    1 |
|  2  |      1  |   100  |    2 |
|  4  |      2  |    95  |    3 |
|  3  |      1  |    90  |    4 |
|  5  |      2  |    80  |    5 |
|  6  |      2  |    80  |    6 |
+-----+---------+--------+------+
Run Code Online (Sandbox Code Playgroud)

Mik*_*ike 2

这有点晚了,但我不确定这是否可以使用递归 CTE 来完成。不过,我确实使用 MODEL 子句提出了一个解决方案:

WITH SAMPLE (ID,GRP_ID,SCORE,RANK) AS (
SELECT 1,1,100,NULL FROM DUAL UNION
SELECT 2,1,90,NULL FROM DUAL UNION
SELECT 3,1,70,NULL FROM DUAL UNION
SELECT 4,2,95,NULL FROM DUAL UNION
SELECT 5,2,70,NULL FROM DUAL UNION
SELECT 6,2,60,NULL FROM DUAL)
SELECT ID,GRP_ID,SCORE,RANK FROM SAMPLE
MODEL
DIMENSION BY (ID,GRP_ID)
MEASURES (SCORE,0 RANK,0 LAST_RANKED_GRP,0 ITEM_COUNT,0 HAS_RANK)
RULES
ITERATE (1000) UNTIL (ITERATION_NUMBER = ITEM_COUNT[1,1]) --ITERATE ONCE FOR EACH ITEM TO BE RANKED
(
RANK[ANY,ANY] = CASE WHEN SCORE[CV(),CV()] = MAX(SCORE) OVER (PARTITION BY HAS_RANK) THEN RANK() OVER (ORDER BY SCORE DESC,ID) ELSE RANK[CV(),CV()] END, --IF THE CURRENT ITEM SCORE IS EQUAL TO THE MAX SCORE OF UNRANKED, ASSIGN A RANK
LAST_RANKED_GRP[ANY,ANY] = FIRST_VALUE(GRP_ID) OVER (ORDER BY RANK DESC),
SCORE[ANY,ANY] = CASE WHEN RANK[CV(),CV()] = 0 AND CV(GRP_ID) = LAST_RANKED_GRP[CV(),CV()] THEN SCORE[CV(),CV()]+10 ELSE SCORE[CV(),CV()] END,
ITEM_COUNT[ANY,ANY] = COUNT(*) OVER (),
HAS_RANK[ANY,ANY] = CASE WHEN RANK[CV(),CV()] <> 0 THEN 1 ELSE 0 END --TO SEPARATE RANKED/UNRANKED ITEMS
)
ORDER BY RANK;
Run Code Online (Sandbox Code Playgroud)

它不是很漂亮,我怀疑有更好的方法来解决这个问题,但它确实给出了预期的输出。

注意事项:

如果行数超过该数量,则必须增加迭代计数。

这会根据每次迭代后的分数进行完整的重新排名。因此,如果我们获取您的样本数据,但将项目 2 的初始分数更改为 95 而不是 90:在对项目 1 进行排名并给予项目 2 10 分奖励后,它现在的分数为 105。因此我们将其排名为第 1并将第 1 项移至第 2 项。如果这不是所需的行为,您必须进行一些修改。