向有序交易组添加唯一 ID
Add unique id to groups of ordered transactions
我目前有一个 table,每个组的交易顺序如下:
| transaction_no | value |
|----------------|-------|
| 1 | 8 |
| 2 | 343 |
| 3 | 28 |
| 4 | 102 |
| 1 | 30 |
| 2 | 5 |
| 3 | 100 |
| 1 | 12 |
| 2 | 16 |
| 3 | 28 |
| 4 | 157 |
| 5 | 125 |
但是我有兴趣添加另一列,为每个列分配一个唯一的 ID
分组(transaction_no 以 1 开始并以 x 结束的交易集
其中紧跟在 x 之后的 transaction_no 是 1)。所以目标是这样的 table:
| transaction_no | value | stmt_id |
|----------------|-------|---------|
| 1 | 8 | 1001 |
| 2 | 343 | 1001 |
| 3 | 28 | 1001 |
| 4 | 102 | 1001 |
| 1 | 30 | 1002 |
| 2 | 5 | 1002 |
| 3 | 100 | 1002 |
| 1 | 12 | 1003 |
| 2 | 16 | 1003 |
| 3 | 28 | 1003 |
| 4 | 157 | 1003 |
| 5 | 125 | 1003 |
我该怎么做?
这是间隙和孤岛问题的变体。为了使其可解决,正如 Gordon Linoff 所评论的那样,您需要一个可用于对行进行排序的列。我假设存在这样一个列并称为 id
.
典型的解决方案涉及对记录进行排名并执行 window 求和。当总排名与 window 总和之间的差异发生变化时,新组开始。
考虑以下查询:
select
id,
transaction,
value,
1000
+ rn
- sum(case when transaction_no = lag_transaction_no + 1 then 1 else 0 end)
over(order by id) grp
from (
select
t.*,
row_number() over(order by id) rn,
lag(transaction_no) over(order by id) lag_transaction_no
from mytable t
) t
使用此样本数据:
id | transaction_no | value
-: | -------------: | ----:
1 | 1 | 8
2 | 2 | 343
3 | 3 | 28
4 | 4 | 102
5 | 1 | 30
6 | 2 | 5
7 | 3 | 100
8 | 1 | 12
9 | 2 | 16
10 | 3 | 28
11 | 4 | 157
12 | 5 | 125
查询returns:
id | transaction_no | value | grp
-: | -------------: | ----: | ---:
1 | 1 | 8 | 1001
2 | 2 | 343 | 1001
3 | 3 | 28 | 1001
4 | 4 | 102 | 1001
5 | 1 | 30 | 1002
6 | 2 | 5 | 1002
7 | 3 | 100 | 1002
8 | 1 | 12 | 1003
9 | 2 | 16 | 1003
10 | 3 | 28 | 1003
11 | 4 | 157 | 1003
12 | 5 | 125 | 1003
我目前有一个 table,每个组的交易顺序如下:
| transaction_no | value |
|----------------|-------|
| 1 | 8 |
| 2 | 343 |
| 3 | 28 |
| 4 | 102 |
| 1 | 30 |
| 2 | 5 |
| 3 | 100 |
| 1 | 12 |
| 2 | 16 |
| 3 | 28 |
| 4 | 157 |
| 5 | 125 |
但是我有兴趣添加另一列,为每个列分配一个唯一的 ID 分组(transaction_no 以 1 开始并以 x 结束的交易集 其中紧跟在 x 之后的 transaction_no 是 1)。所以目标是这样的 table:
| transaction_no | value | stmt_id |
|----------------|-------|---------|
| 1 | 8 | 1001 |
| 2 | 343 | 1001 |
| 3 | 28 | 1001 |
| 4 | 102 | 1001 |
| 1 | 30 | 1002 |
| 2 | 5 | 1002 |
| 3 | 100 | 1002 |
| 1 | 12 | 1003 |
| 2 | 16 | 1003 |
| 3 | 28 | 1003 |
| 4 | 157 | 1003 |
| 5 | 125 | 1003 |
我该怎么做?
这是间隙和孤岛问题的变体。为了使其可解决,正如 Gordon Linoff 所评论的那样,您需要一个可用于对行进行排序的列。我假设存在这样一个列并称为 id
.
典型的解决方案涉及对记录进行排名并执行 window 求和。当总排名与 window 总和之间的差异发生变化时,新组开始。
考虑以下查询:
select
id,
transaction,
value,
1000
+ rn
- sum(case when transaction_no = lag_transaction_no + 1 then 1 else 0 end)
over(order by id) grp
from (
select
t.*,
row_number() over(order by id) rn,
lag(transaction_no) over(order by id) lag_transaction_no
from mytable t
) t
使用此样本数据:
id | transaction_no | value -: | -------------: | ----: 1 | 1 | 8 2 | 2 | 343 3 | 3 | 28 4 | 4 | 102 5 | 1 | 30 6 | 2 | 5 7 | 3 | 100 8 | 1 | 12 9 | 2 | 16 10 | 3 | 28 11 | 4 | 157 12 | 5 | 125
查询returns:
id | transaction_no | value | grp -: | -------------: | ----: | ---: 1 | 1 | 8 | 1001 2 | 2 | 343 | 1001 3 | 3 | 28 | 1001 4 | 4 | 102 | 1001 5 | 1 | 30 | 1002 6 | 2 | 5 | 1002 7 | 3 | 100 | 1002 8 | 1 | 12 | 1003 9 | 2 | 16 | 1003 10 | 3 | 28 | 1003 11 | 4 | 157 | 1003 12 | 5 | 125 | 1003