PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Попълване на произволни данни от друга таблица

НАСТРОЙКА

Нека започнем, като приемем, че вашите таблици и данни са следните. Имайте предвид, че предполагам, че 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 тук



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да предам низ с „ “ (клеймо за време) в подготвено изявление?

  2. Създаване на релационни връзки в PostgreSQL чрез pgAdmin

  3. цел на сортиране в Postgres

  4. Запитване за персонализиран параметър postgresql с оператор SELECT

  5. вземете таблица JOIN като масив от резултати с PostgreSQL/NodeJS