THIẾT LẬP
Hãy bắt đầu bằng cách giả sử các bảng của bạn có một dữ liệu sau đây. Lưu ý rằng tôi giả sử rằng dataset1
có một khóa chính (nó có thể là một khóa tổng hợp, nhưng để đơn giản, hãy đặt nó là một số nguyên):
CREATE TABLE dataset1
(
id INTEGER PRIMARY KEY,
column4 TEXT
) ;
CREATE TABLE dataset2
(
column1 TEXT
) ;
Chúng tôi điền vào cả hai bảng với dữ liệu mẫu
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) ;
Kiểm tra tình trạng:
SELECT count(DISTINCT column4) FROM dataset1 ;
| count | | ----: | | 20 |
Trường hợp 1:số hàng trong tập dữ liệu1 <=hàng trong tập dữ liệu2
Chúng tôi sẽ thực hiện xáo trộn hoàn chỉnh. Các giá trị từ dataset2 sẽ được sử dụng một lần và không nhiều hơn một lần.
GIẢI THÍCH
Để thực hiện cập nhật xáo trộn tất cả các giá trị từ column4
trong thời trang arandom, chúng tôi cần một số bước trung gian.
Đầu tiên, đối với dataset1
, chúng ta cần tạo một danh sách (quan hệ) các bộ giá trị (id, rn)
, đó chỉ là:
(id_1, 1),
(id_2, 2),
(id_3, 3),
...
(id_20, 20)
Ở đâu id_1
, ..., id_20
id có trên dataset1
không Chúng có thể thuộc bất kỳ loại nào, không cần liên tiếp và có thể là hỗn hợp.
Đối với dataset2
, chúng tôi cần tạo một danh sách khác gồm (column_1,rn)
, trông giống như:
(column1_1, 17),
(column1_2, 3),
(column1_3, 11),
...
(column1_20, 15)
Trong trường hợp này, cột thứ hai chứa tất cả các giá trị 1 .. 20, nhưng bị xáo trộn.
Khi chúng ta có hai mối quan hệ, chúng ta JOIN
chúng ON ... rn
. Trên thực tế, điều này tạo ra một danh sách các bộ giá trị khác có (id, column1)
, nơi việc ghép đôi đã được thực hiện một cách ngẫu nhiên. Chúng tôi sử dụng các cặp này để cập nhật dataset1
.
CÂU HỎI THỰC TẾ
Tất cả điều này có thể được thực hiện (rõ ràng, tôi hy vọng) bằng cách sử dụng một số CTE (WITH
câu lệnh) để giữ các quan hệ trung gian:
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 ;
Lưu ý rằng thủ thuật được thực hiện bằng:
row_number() OVER (ORDER BY random()) AS rn
row_number()
chức năng cửa sổ
tạo ra nhiều số liên tiếp như có các hàng, bắt đầu từ 1. Các số này được xáo trộn ngẫu nhiên vì OVER
mệnh đề lấy tất cả dữ liệu và sắp xếp nó một cách ngẫu nhiên.
KIỂM TRA
Chúng tôi có thể kiểm tra lại:
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
ĐẠI SỐ
Lưu ý rằng điều này cũng có thể được thực hiện với các truy vấn con, bằng cách thay thế đơn giản, thay vì CTE. Điều đó có thể cải thiện hiệu suất trong một số trường hợp:
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 ;
Và một lần nữa ...
SELECT * FROM dataset1;
id | column4 --: | :------------- 101 | SOMETHING 1011 102 | SOMETHING 1018 103 | SOMETHING 1007 ... 118 | SOMETHING 1020 119 | SOMETHING 1002 120 | SOMETHING 1016
Bạn có thể kiểm tra toàn bộ thiết lập và thử nghiệm tại dbfiddle tại đây
LƯU Ý:nếu bạn thực hiện việc này với bộ dữ liệu rất lớn, đừng mong đợi nó cực kỳ nhanh. Việc xáo trộn một bộ bài rất lớn rất tốn kém.
Trường hợp 2:số hàng trong tập dữ liệu1> hàng trong tập dữ liệu2
Trong trường hợp này, các giá trị cho column4
có thể được lặp lại nhiều lần.
Khả năng dễ nhất mà tôi có thể nghĩ đến (có thể, không phải là một cách hiệu quả, nhưng dễ hiểu) là tạo một hàm random_column1
, được đánh dấu là VOLATILE
:
CREATE FUNCTION random_column1()
RETURNS TEXT
VOLATILE -- important!
LANGUAGE SQL
AS
$$
SELECT
column1
FROM
dataset2
ORDER BY
random()
LIMIT
1 ;
$$ ;
Và sử dụng nó để cập nhật:
UPDATE
dataset1
SET
column4 = random_column1();
Bằng cách này, một số giá trị từ dataset2
might hoàn toàn không được sử dụng, trong khi những người khác sẽ được sử dụng nhiều lần.
dbfiddle tại đây