MySQL -组内计数器

unhi4e5o  于 2023-05-21  发布在  Mysql
关注(0)|答案(2)|浏览(154)

我想添加一个计数器为每一行内的一组根据一个升序变量。我有一个解决方案,但如果组内的某些变量相等,则它不起作用:

CREATE TABLE tb (
g CHAR(1)
, x  INTEGER
);

INSERT INTO tb (g, x)
VALUES
('a',1)
, ('a',2)
, ('a',10)
, ('b',1)
, ('b',1)
, ('b',10)
;

SELECT g,x, (SELECT COUNT(*)
           FROM tb b
           WHERE a.g = b.g
                 AND a.x > b.x
           ) + 1 AS counter
FROM tb a
;

我得到的是:

--------------------
| g | x  | counter |
--------------------
| a |  1 |    1    |  
| a |  2 |    2    |  
| a | 10 |    3    |
| b |  1 |    1    |
| b |  1 |    1    |
| b | 10 |    3    |
--------------------

但我想得到:

--------------------
| g | x  | counter |
--------------------
| a |  1 |    1    |  
| a |  2 |    2    |  
| a | 10 |    3    |
| b |  1 |    1    |
| b |  1 |    2    |
| b | 10 |    3    |
--------------------

你知道我怎么解决这个问题吗?多谢你的提示。
焦尔达诺

ffx8fchx

ffx8fchx1#

用户定义的变量在解决这个问题时变得很方便。这应该可以工作:

select g, x, counter from (
    select g, x,
        @counter := if (g = @prev_g, @counter + 1, 1) counter,
        @prev_g := g
    from tb, (select @counter := 0, @prev_g := null) init
    order by g, x
) s

如果你真的不介意第四列,那么你可以安全地删除外部选择。这将大大提高性能。

cczfrluj

cczfrluj2#

因为MariaDB/MySQL的新版本使用用户定义的变量可能会导致错误的结果。使用window functions代替用户定义的变量:

SELECT tb.*
     , ROW_NUMBER() OVER(PARTITION BY g ORDER BY g,x) counter
FROM test0.tb

查看这里了解更多为什么用户定义的变量是危险的。

相关问题