有没有办法仅使用 SQL 将 table 中的行洗牌成独特的固定大小块?

Is there a way to shuffle rows in a table into distinctive fixed size chunks using SQL only?

我有一个非常大的 table(约 3 亿行),其结构如下: my_table(id, group, chunk, new_id),其中chunk和new_id设置为NULL。

我想将每个组的行设置为一个随机块,块中有不同的 new_id。每个块的大小应固定为 100。

例如,如果组 A 有 1278 行,则它们应分为 13 个块 (0-12),12 个块,100 行 s.t。 new_id 在范围 (0-99) 内,另一个包含 78 行的块 s.t。 new_id 在范围 (0-77) 内。

块中和块内的组织应该是随机排列,其中 A 中的每一行都分配有唯一的(块,new_id)元组。

我使用 pandas 成功地做到了,但它需要几个小时,主要是由于内存和带宽限制。

是否可以仅使用 SQL 查询来执行? 我正在使用 postgres 9.6。

你可以用 row_number():

select id, group, rn / 100 chunk, rn % 100 new_id
from (select t.*, row_number() over(order by random()) - 1 rn from mytable t) t

内部查询为每条记录分配一个随机整数(从 0 开始)。外部查询通过算术计算块和新 ID。

如果您想要 update 查询:

update mytable t set chunk = x.rn / 3, new_id = x.rn % 3
from (select id, row_number() over(order by random()) - 1 rn from mytable t) x
where x.id = t.id

Demo on DB Fiddle 对于包含 3 条记录的 20 条记录的数据集。

之前:

id | grp | chunk | new_id
-: | --: | ----: | -----:
 1 |   1 |  nullnull
 2 |   2 |  nullnull
 3 |   3 |  nullnull
 4 |   4 |  nullnull
 5 |   5 |  nullnull
 6 |   6 |  nullnull
 7 |   7 |  nullnull
 8 |   8 |  nullnull
 9 |   9 |  nullnull
10 |  10 |  nullnull
11 |  11 |  nullnull
12 |  12 |  nullnull
13 |  13 |  nullnull
14 |  14 |  nullnull
15 |  15 |  nullnull
16 |  16 |  nullnull
17 |  17 |  nullnull
18 |  18 |  nullnull
19 |  19 |  nullnull
20 |  20 |  nullnull

之后:

id | grp | chunk | new_id
-: | --: | ----: | -----:
19 |  19 |     0 |      0
11 |  11 |     0 |      1
20 |  20 |     0 |      2
12 |  12 |     1 |      0
14 |  14 |     1 |      1
17 |  17 |     1 |      2
 3 |   3 |     2 |      0
 8 |   8 |     2 |      1
 5 |   5 |     2 |      2
13 |  13 |     3 |      0
10 |  10 |     3 |      1
 2 |   2 |     3 |      2
16 |  16 |     4 |      0
18 |  18 |     4 |      1
 6 |   6 |     4 |      2
 1 |   1 |     5 |      0
15 |  15 |     5 |      1
 7 |   7 |     5 |      2
 4 |   4 |     6 |      0
 9 |   9 |     6 |      1