2017-08-04 29 views
3
update dataset1.test 
    set column4 = (select column1 
       from dataset2 
       order by random() 
       limit 1 
       ) 

我必須更新第4列的dataset1,每行更新從數據集2列的隨機條目..但到目前爲止,在上面的查詢中,我只有一個隨機條目在所有數據集1的行及其所有我想要它隨機的相同。從另一個表填充隨機數據

+0

一些問題:你會允許從一個值'dataset2'使用上'dataset1'多次,還是每個值都將最多隻用一次? 'dataset2'是否至少與'dataset1'一樣多? –

+0

[SQl從隨機名稱表更新](https://stackoverflow.com/questions/21560392/sql-update-from-table-of-random-names)可能有重複。假設你在數據集2上有一個數字ID。 – JeffUK

+0

[Redshift:使用另一個表中的隨機數據更新或插入列中的每一行可能的重複](https://stackoverflow.com/questions/45535038/redshift-update-or-insert-each-row-in-column- with-random-data-from-another-tabl) –

回答

3

SETUP假設你的表的數據是下述的

讓我們開始。 請注意,我假設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 ; 
 
| count | 
| ----: | 
| 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是IDS提出關於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

THE REAL QUERY

這都是可以做的(顯然,我希望)通過使用一些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() window function,它從1開始產生儘可能多的連續數字,從1開始。 這些數字是隨機洗牌的,因爲OVER子句獲取所有數據並將其隨機分類。

支票

我們可以再次檢查:

SELECT count(DISTINCT column4) FROM dataset1 ; 
 
| count | 
| ----: | 
| 20 | 
SELECT * FROM dataset1 ; 
 
id | column4  
--: | :------------- 
101 | SOMETHING 1016 
102 | SOMETHING 1009 
103 | SOMETHING 1003 
... 
118 | SOMETHING 1012 
119 | SOMETHING 1017 
120 | SOMETHING 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 | column4  
--: | :------------- 
101 | SOMETHING 1011 
102 | SOMETHING 1018 
103 | SOMETHING 1007 
... 
118 | SOMETHING 1020 
119 | SOMETHING 1002 
120 | SOMETHING 1016 

您可以在dbfiddle檢查整個設置和實驗here

注意:如果你用非常大的數據集做這件事,不要期望它速度非常快。洗牌很大一套很昂貴。


情況2:在數據集1的行數>在dataset2

在這種情況下的行,用於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 here

+0

嘿你的查詢似乎合法..但有一件事,我忘了提及數據集1大於dataset2 ..因此,例如數據集2可以有50個數據,如果數據集1有100個數據。 - >即使數值出現10次,數據集1也應使用數據集2中的隨機值進行更新 –

+0

您應該編輯您的問題並添加此信息。任何可能的答案都會受到很大影響。 – joanolo

+0

在我的回答中參見**案例2 **。 – joanolo

0

更好是從子查詢引用的外部表。然後,子查詢必須evalued的每一行:

update dataset1.test 
    set column4 = (select 
     case when dataset1.test.column4 = dataset1.test.column4 
      then column1 end 
     from dataset2 
     order by random() 
     limit 1 
    )