我在一轮面试中遇到了这个问题。表具有以下列。
| ID |
|---|
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
| 11 |
| 12 |
| 13 |
| 14 |
| 15 |
| 16 |
| 17 |
| 18 |
| 19 |
| 20 |
| 22 |
| 23 |
| 24 |
| 26 |
问题是创建一个以“1”开头的新列,只要有 5 的倍数,就在下一个 ID 上递增。所以预期的输出是
| ID | 结果 |
|---|---|
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 5 | 1 |
| 6 | 2 |
| 7 | 2 |
| 8 | 2 |
| 9 | 2 |
| 11 | 2 |
| 12 | 2 |
| 13 | 2 |
| 14 | 2 |
| 15 | 2 |
| 16 | 3 |
| 17 | 3 |
| 18 | 3 |
| 19 | 3 |
| 20 | 3 |
| 22 | 4 |
| 23 | 4 |
| 24 | 4 |
| 26 | 4 |
我在一轮面试中遇到了这个问题。表具有以下列。
| ID |
|---|
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
| 11 |
| 12 |
| 13 |
| 14 |
| 15 |
| 16 |
| 17 |
| 18 |
| 19 |
| 20 |
| 22 |
| 23 |
| 24 |
| 26 |
问题是创建一个以“1”开头的新列,只要有 5 的倍数,就在下一个 ID 上递增。所以预期的输出是
| ID | 结果 |
|---|---|
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 5 | 1 |
| 6 | 2 |
| 7 | 2 |
| 8 | 2 |
| 9 | 2 |
| 11 | 2 |
| 12 | 2 |
| 13 | 2 |
| 14 | 2 |
| 15 | 2 |
| 16 | 3 |
| 17 | 3 |
| 18 | 3 |
| 19 | 3 |
| 20 | 3 |
| 22 | 4 |
| 23 | 4 |
| 24 | 4 |
| 26 | 4 |
您可以组合两个窗口函数:LAG()和SUM()。例如:
select id,
1 + sum(case when lid % 5 = 0 then 1 else 0 end) over(order by id) as v
from (
select *, lag(id) over(order by id) as lid from t
) x
order by id
结果:
id v
-- -
1 1
2 1
3 1
4 1
5 1
6 2
7 2
8 2
9 2
11 2
12 2
13 2
14 2
15 2
16 3
17 3
18 3
19 3
20 3
22 4
23 4
24 4
26 4
请参阅DB Fiddle上的运行示例。
例如,对于 MySQL 5+,您可以使用
SELECT id, (@result := COALESCE( @result + !(id % 5), 1 )) - !(id % 5) result
FROM t
CROSS JOIN (SELECT @result := NULL) init_variable
ORDER BY id
对于 MySQL 8+ 使用
SELECT id, 1 + SUM(!(id % 5)) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) resuls
FROM t
您可以在没有子查询的情况下执行此操作:
select t.*,
1 + sum( (id % 5) = 0 ) over (order by id) - (id % 5 = 0)
from t
order by id;
这里的逻辑是什么?计算直到这一行的“5”的累积和。然后减去这一行的值,因为增量对下一行生效。
使用窗口框架子句编写它也很诱人,但最终会稍微复杂一些,因为第一个值是NULL:
select t.*,
1 + coalesce(sum( (id % 5) = 0 ) over (order by id rows between unbounded preceding and 1 preceding), 0)
from t
order by id;
这是一个 db<>fiddle。