Есть ли способ перемешать строки в таблице в отдельные фрагменты фиксированного размера, используя только SQL? - PullRequest
1 голос
/ 14 января 2020

У меня очень большая таблица (~ 300 миллионов строк) со следующей структурой: my_table (id, group, chunk, new_id), где chunk и new_id установлены в NULL.

Я хочу установить строки каждой группы в случайный кусок с отличным new_id в чанке. Каждый блок должен иметь фиксированный размер 100.

Например, если в группе А 1278 строк, они должны go разделиться на 13 блоков (0-12), 12 блоков с 100 строками st new_id находятся в диапазоне ( 0-99) и еще один отдельный блок с 78 строками st new_id находятся в диапазоне (0-77).

Организация в чанках и в чанках должна быть случайной перестановкой, где каждой строке в A назначается уникальный (chunk, new_id) кортеж.

Я успешно делаю это с помощью pandas но это занимает часы, в основном из-за ограничений памяти и пропускной способности.

Можно ли выполнить, используя только запрос SQL? Я использую postgres 9.6.

1 Ответ

1 голос
/ 14 января 2020

Вы можете сделать это с помощью 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). Внешний запрос выполняет арифметику c для вычисления фрагмента и нового идентификатора.

Если вы хотите запрос 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

Демонстрация на DB Fiddle для набора данных из 20 записей с кусками из 3 записей.

До:

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

После:

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
...