SQL分区按原始顺序

时间:2020-10-07 20:51:52

标签: mysql sql window-functions gaps-and-islands

这是原始的MySQL表:

+----+-----+
| Id | Num |
+----+-----+
| 1  |  1  |
| 2  |  1  |
| 3  |  1  |
| 4  |  2  |
| 5  |  1  |
| 6  |  2  |
| 7  |  2  |
+----+-----+

当我使用select Id, Num, row_number() over(partition by Num) from t时,MySQL自动中断Num列的顺序。但是,我想保持Num列的顺序不变。 具体来说,理想的输出应为:

+----+-----+-----+
| Id | Num | row |
+----+-----+-----+
| 1  |  1  |  1  |
| 2  |  1  |  2  |
| 3  |  1  |  3  |
| 4  |  2  |  1  |
| 5  |  1  |  1  |
| 6  |  2  |  1  |
| 7  |  2  |  2  |
+----+-----+-----+

如何编写此MySQL查询?

3 个答案:

答案 0 :(得分:2)

这是一个空白问题。我建议使用行号之间的差异来识别组。

如果id总是无间隙递增:

select id, num, 
    row_number() over(partition by num, id - rn order by id) rn
from (
    select t.*, row_number() over(partition by num order by id) rn
    from mytable t
) t
order by id

否则,我们可以使用另一个id生成自己的增量row_number()

select id, num, 
    row_number() over(partition by num, rn1 - rn2 order by id) rn
from (
    select t.*, 
        row_number() over(order by id) rn1,
        row_number() over(partition by num order by id) rn2
    from mytable t
) t
order by id

Demo on DB Fiddle -对于您的示例数据,两个查询都产生:

id | num | rn
-: | --: | -:
 1 |   1 |  1
 2 |   1 |  2
 3 |   1 |  3
 4 |   2 |  1
 5 |   1 |  1
 6 |   2 |  1
 7 |   2 |  2

答案 1 :(得分:1)

您可以通过writing your own row_number进行此操作,以更好地控制其分区。

set @prev_num = null;
set @row_number = 0;

select
  id,
  -- Reset row_number to 1 whenever num changes, else increment it.
  @row_number := case
    when @prev_num = num then 
      @row_number + 1
    else
      1
    end as `row_number`,
  -- Emulate lag(). This must come after the row_number.
  @prev_num := num as num
from foo
order by id;

答案 2 :(得分:0)

与Schwern提出的解决方案相同的想法。我发现MySQL的另一种语法风格非常简单且易于使用。

.toBeHidden{
  position: relative;
}
.overlay{
  position: absolute;
  height: 100%;
  width: 100%;
  background-color: red;
  color: white;
 }

DB小提琴链接-https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=e04692841d091ccd54ee3435a409c67a

相关问题