НАСТРОЙКА
Нека започнем, като приемем, че вашите таблици и данни са следните. Имайте предвид, че предполагам, че dataset1
има първичен ключ (той може да бъде съставен, но за по-голяма простота нека го направим цяло число):
CREATE TABLE dataset1
(
id INTEGER PRIMARY KEY,
column4 TEXT
) ;
CREATE TABLE dataset2
(
column1 TEXT
) ;
Попълваме и двете таблици с примерни данни
INSERT INTO dataset1
(id, column4)
SELECT
i, 'column 4 for id ' || i
FROM
generate_series(101, 120) AS s(i);
INSERT INTO dataset2
(column1)
SELECT
'SOMETHING ' || i
FROM
generate_series (1001, 1020) AS s(i) ;
Проверка на разума:
SELECT count(DISTINCT column4) FROM dataset1 ;
<преди>| брои || ----:|| 20 | Случай 1:брой редове в набор от данни1 <=редове в набор от данни2
Ще извършим пълно разместване. Стойностите от dataset2 ще бъдат използвани веднъж и не повече от веднъж.
ОБЯСНЕНИЕ
За да направите актуализация, която разбърква всички стойности от column4
по случаен начин се нуждаем от някои междинни стъпки.
Първо, за dataset1
, трябва да създадем списък (релация) от кортежи (id, rn)
, това са само:
(id_1, 1),
(id_2, 2),
(id_3, 3),
...
(id_20, 20)
Където id_1
, ..., id_20
са идентификаторите, налични в dataset1
.Могат да бъдат от всякакъв тип, не е необходимо да са последователни и могат да бъдат съставни.
За dataset2
, трябва да създадем друг списък от (column_1,rn)
, това изглежда така:
(column1_1, 17),
(column1_2, 3),
(column1_3, 11),
...
(column1_20, 15)
В този случай втората колона съдържа всички стойности 1 .. 20, но разбъркани.
След като имаме двете релации, ние JOIN
тях ON ... rn
. Това на практика създава още един списък от кортежи с (id, column1)
, където сдвояването е извършено на случаен принцип. Използваме тези двойки, за да актуализираме dataset1
.
ИСТИНСКОТО ЗАПИТВАНЕ
Всичко това може да бъде направено (надявам се, ясно) с помощта на някои CTE (WITH
оператор), за да поддържа междинните връзки:
WITH original_keys AS
(
-- This creates tuples (id, rn),
-- where rn increases from 1 to number or rows
SELECT
id,
row_number() OVER () AS rn
FROM
dataset1
)
, shuffled_data AS
(
-- This creates tuples (column1, rn)
-- where rn moves between 1 and number of rows, but is randomly shuffled
SELECT
column1,
-- The next statement is what *shuffles* all the data
row_number() OVER (ORDER BY random()) AS rn
FROM
dataset2
)
-- You update your dataset1
-- with the shuffled data, linking back to the original keys
UPDATE
dataset1
SET
column4 = shuffled_data.column1
FROM
shuffled_data
JOIN original_keys ON original_keys.rn = shuffled_data.rn
WHERE
dataset1.id = original_keys.id ;
Имайте предвид, че трикът се извършва чрез:
row_number() OVER (ORDER BY random()) AS rn
row_number()
функция прозорец
който произвежда толкова последователни числа, колкото има редове, като се започне от 1. Тези числа се разбъркват на случаен принцип, защото OVER
клауза взема всички данни и ги сортира на случаен принцип.
ЧЕКОВЕ
Можем да проверим отново:
SELECT count(DISTINCT column4) FROM dataset1 ;
<преди>| брои || ----:|| 20 | SELECT * FROM dataset1 ;
id | колона4 --:| :-------------101 | НЕЩО 1016102 | НЕЩО 1009103 | НЕЩО 1003...118 | НЕЩО 1012119 | НЕЩО 1017120 | НЕЩО 1011
АЛТЕРНАТИВА
Обърнете внимание, че това може да се направи и с подзаявки, чрез просто заместване, вместо CTE. Това може да подобри производителността в някои случаи:
UPDATE
dataset1
SET
column4 = shuffled_data.column1
FROM
(SELECT
column1,
row_number() OVER (ORDER BY random()) AS rn
FROM
dataset2
) AS shuffled_data
JOIN
(SELECT
id,
row_number() OVER () AS rn
FROM
dataset1
) AS original_keys ON original_keys.rn = shuffled_data.rn
WHERE
dataset1.id = original_keys.id ;
И отново...
SELECT * FROM dataset1 ;
id | колона4 --:| :-------------101 | НЕЩО 1011102 | НЕЩО 1018103 | НЕЩО 1007...118 | НЕЩО 1020119 | НЕЩО 1002120 | НЕЩО 1016
Можете да проверите цялата настройка и експеримент в dbfiddle тук
ЗАБЕЛЕЖКА:ако правите това с много големи масиви от данни, не очаквайте да бъде изключително бързо. Разбъркването на много голямо тесте карти е скъпо.
Случай 2:брой редове в набор от данни1> редове в набор от данни2
В този случай, стойности за column4
може да се повтори няколко пъти.
Най-лесната възможност, за която се сещам (вероятно не ефективна, но лесна за разбиране) е да създам функция random_column1
, означен като VOLATILE
:
CREATE FUNCTION random_column1()
RETURNS TEXT
VOLATILE -- important!
LANGUAGE SQL
AS
$$
SELECT
column1
FROM
dataset2
ORDER BY
random()
LIMIT
1 ;
$$ ;
И го използвайте за актуализиране:
UPDATE
dataset1
SET
column4 = random_column1();
По този начин някои стойности от dataset2
може няма да се използва изобщо, докато други ще да се използва повече от веднъж.
dbfiddle тук