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 ;
| 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 यहां



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PostgreSQL के लिए शीर्ष बैकअप उपकरण

  2. रेल में LOWER (users.username) पर इंडेक्स कैसे बनाएं (पोस्टग्रेज का उपयोग करके)

  3. JDBC और Postgres का उपयोग करके IN क्लॉज में अज्ञात संख्या में पैरामीटर पास करें

  4. पोस्टग्रेज टाइमस्टैम्प

  5. पूरे पन्ने के प्रभाव पर लिखता है