सेटअप
आइए मान लें कि आपकी तालिकाएँ एक डेटा निम्नलिखित हैं। ध्यान दें कि मुझे लगता है कि 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 में पंक्तियां
हम पूरी तरह से फेरबदल करेंगे। डेटासेट2 के मानों का एक बार उपयोग किया जाएगा, और एक से अधिक बार नहीं।
व्याख्या
एक अपडेट करने के लिए जो 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
. को अपडेट करने के लिए करते हैं ।
असली प्रश्न
यह सब कुछ सीटीई (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 ;
| 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
वैकल्पिक
ध्यान दें कि यह सीटीई के बजाय, सरल प्रतिस्थापन द्वारा, उपश्रेणियों के साथ भी किया जा सकता है। इससे कुछ मौकों पर प्रदर्शन में सुधार हो सकता है:
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 यहां पर पूरे सेटअप और प्रयोग की जांच कर सकते हैं।
नोट:यदि आप इसे बहुत बड़े डेटासेट के साथ करते हैं, तो यह अपेक्षा न करें कि यह बहुत तेज़ होगा। ताश के पत्तों का एक बहुत बड़ा डेक फेरबदल करना महंगा है।
केस 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 यहां