2011-02-15 12 views
52
UPDATE CattleProds 
SET SheepTherapy=(ROUND((RAND()* 10000),0)) 
WHERE SheepTherapy IS NULL 

में समान मान मिलता है, तो मैं तो एक का चयन मैं देख रहा हूँ कि मेरी यादृच्छिक संख्या identical in every row है। कोई भी विचार अद्वितीय यादृच्छिक संख्या कैसे उत्पन्न करें?मैं SQL में यादृच्छिक संख्या वाले कॉलम को कैसे भर सकता हूं? मैं हर पंक्ति

+1

इस प्रश्न/उत्तर सहायक हो सकता है: http://stackoverflow.com/a/9039661/47226 –

उत्तर

114

rand() के बजाय, newid() का उपयोग करें, जो परिणाम में प्रत्येक पंक्ति के लिए पुन: गणना की जाती है। सामान्य तरीका चेकसम के मॉड्यूल का उपयोग करना है। ध्यान दें कि checksum(newid()) -2,147,483,648 उत्पन्न कर सकता है और abs() पर पूर्णांक ओवरफ़्लो का कारण बन सकता है, इसलिए हमें इसे पूर्ण मूल्य में परिवर्तित करने से पहले चेकसम रिटर्न मान पर मॉड्यूलो का उपयोग करने की आवश्यकता है।

UPDATE CattleProds 
SET SheepTherapy = abs(checksum(NewId()) % 10000) 
WHERE SheepTherapy IS NULL 

यह 0 और 9999

+0

यह प्रश्न/उत्तर भी सहायक हो सकता है: http://stackoverflow.com/a/ 9039661/47226 –

+1

वोट दिया गया क्योंकि मैं इसे संदर्भ के रूप में उपयोग करता रहता हूं। –

+0

यह मेरे लिए बिल्कुल काम नहीं कर रहा है। क्या कॉलम इंट होना चाहिए? हर बार त्रुटि # 1064। पागल गोलियों के लिए पहुंच ... – freeworlder

19

के बीच एक यादृच्छिक संख्या आप भी

CRYPT_GEN_RANDOM(2) % 10000 

उपयोग कर सकते हैं आप एसक्यूएल सर्वर 2008 पर हैं, तो कुछ हद तक सरल लगता है कौन उत्पन्न करता है (यह भी एक बार प्रति मूल्यांकन किया जाता है newid के रूप में पंक्ति - नीचे दिखाया गया है)

DECLARE @foo TABLE (col1 FLOAT) 

INSERT INTO @foo SELECT 1 UNION SELECT 2 

UPDATE @foo 
SET col1 = CRYPT_GEN_RANDOM(2) % 10000 

SELECT * FROM @foo 

रिटर्न (2 यादृच्छिक शायद अलग संख्या)

col1 
---------------------- 
9693 
8573 

केवल वैध कारण मुझे लगता है कि यादृच्छिक जनरेट की गई संख्या 0-65,535 के बीच है जिसकी वजह से नहीं समान रूप से विभाज्य 10,000 कुछ संख्या का प्रतिनिधित्व करती खत्म हो गया है थोड़ा हो जाएगा के बारे में सोच सकते हैं downvote अस्पष्टीकृत विचार कर रही । इसके आस-पास एक तरीका एक स्केलर यूडीएफ में लपेटना होगा जो किसी भी संख्या को 60,000 से अधिक दूर फेंक देगा और प्रतिस्थापन संख्या प्राप्त करने के लिए खुद को रिकर्सिव रूप से कॉल करेगा।

CREATE FUNCTION dbo.RandomNumber() 
RETURNS INT 
AS 
    BEGIN 
     DECLARE @Result INT 

     SET @Result = CRYPT_GEN_RANDOM(2) 

     RETURN CASE 
       WHEN @Result < 60000 
        OR @@NESTLEVEL = 32 THEN @Result % 10000 
       ELSE dbo.RandomNumber() 
      END 
    END 
+1

@downvoter - कोई विशेष कारण? शायद आप ऊपर तीर मारना चाहते थे यह जवाब ठीक काम करता है! –

+0

क्या हर कोई गायब होने लगता है यह है कि यह विधि प्रदर्शन के लिए बहुत अधिक बेहतर है। मैं NEWID() के लिए एक विकल्प की तलाश में हूं और यह धन्यवाद है, धन्यवाद! – Digs

6

जब मैं अंततः का उपयोग कर प्यार करते हो, मैं तुम्हें एक जटिल गणित के माध्यम से जाने के लिए सरल संख्या उत्पन्न करने के लिए की जरूरत नहीं है सिर्फ इसलिए कि एक बेहतर तरीका) जाने के लिए NEWID (उपयोग कर रहा है, लग रहा है।

ROUND(1000 *RAND(convert(varbinary, newid())), 0) 

आप 1000 के साथ जो भी नंबर पर आप सीमा के रूप में सेट करना चाहते हैं जगह ले सकता है, और आप हमेशा एक श्रृंखला बनाने के लिए धन चिह्न का उपयोग कर सकते, मान लीजिए कि आप चाहते हैं 100 और 200 के बीच एक यादृच्छिक संख्या, आप कर सकते हैं करते हैं आपकी क्वेरी में एक साथ यह लाना

100 + ROUND(100 *RAND(convert(varbinary, newid())), 0) 

:

UPDATE CattleProds 
SET SheepTherapy= ROUND(1000 *RAND(convert(varbinary, newid())), 0) 
WHERE SheepTherapy IS NULL 
0

मैं रैंड के खिलाफ 2 सेट आधारित यादृच्छिकीकरण तरीकों का परीक्षण किया() प्रत्येक के साथ 100,000,000 पंक्तियों उत्पन्न करके की तरह कुछ है। फ़ील्ड को स्तरित करने के लिए आउटपुट 0-1 के बीच रैंड() की नकल है। कोड के अधिकांश बुनियादी ढांचे परीक्षण कर रहा है तो मैं एल्गोरिदम यहाँ संक्षेप में प्रस्तुत:

-- Try #1 used 
(CAST(CRYPT_GEN_RANDOM(8) AS BIGINT)%500000000000000000+500000000000000000.0)/1000000000000000000 AS Val 
-- Try #2 used 
RAND(Checksum(NewId())) 
-- and to have a baseline to compare output with I used 
RAND() -- this required executing 100000000 separate insert statements 

CRYPT_GEN_RANDOM का उपयोग करते हुए स्पष्ट रूप से सबसे यादृच्छिक के बाद से वहाँ भी 1 डुप्लिकेट जब एक से 10^8 संख्या तोड़ देखने का केवल एक ०.००००००००१% मौका है था 10^18 संख्याओं का सेट। आइओ हमें किसी भी डुप्लीकेट नहीं दिखना चाहिए था और इसमें कोई नहीं था! इस सेट में मेरे लैपटॉप पर उत्पन्न होने के लिए 44 सेकंड लग गए।

Cnt  Pct 
----- ---- 
1  100.000000 --No duplicates 

एसक्यूएल सर्वर निष्पादन समय: CPU समय = 134,795 एमएस, बीता हुआ समय = 39,274 एमएस।

IF OBJECT_ID('tempdb..#T0') IS NOT NULL DROP TABLE #T0; 
GO 
WITH L0 AS (SELECT c FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS D(c)) -- 2^4 
    ,L1 AS (SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B) -- 2^8 
    ,L2 AS (SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B) -- 2^16 
    ,L3 AS (SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B) -- 2^32 
SELECT TOP 100000000 (CAST(CRYPT_GEN_RANDOM(8) AS BIGINT)%500000000000000000+500000000000000000.0)/1000000000000000000 AS Val 
    INTO #T0 
    FROM L3; 

WITH x AS (
    SELECT Val,COUNT(*) Cnt 
     FROM #T0 
    GROUP BY Val 
) 
SELECT x.Cnt,COUNT(*)/(SELECT COUNT(*)/100 FROM #T0) Pct 
    FROM X 
GROUP BY x.Cnt; 

पर लगभग 15 परिमाण कम यादृच्छिक इस पद्धति काफी दोगुनी गति से नहीं था, केवल 23 सेकंड लेने 100M संख्या उत्पन्न करने के लिए।

Cnt Pct 
---- ---- 
1 95.450254 -- only 95% unique is absolutely horrible 
2 02.222167 -- If this line were the only problem I'd say DON'T USE THIS! 
3 00.034582 
4 00.000409 -- 409 numbers appeared 4 times 
5 00.000006 -- 6 numbers actually appeared 5 times 

एसक्यूएल सर्वर निष्पादन समय: CPU समय = 77,156 एमएस, बीता हुआ समय = 24,613 एमएस।

IF OBJECT_ID('tempdb..#T1') IS NOT NULL DROP TABLE #T1; 
GO 
WITH L0 AS (SELECT c FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS D(c)) -- 2^4 
    ,L1 AS (SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B) -- 2^8 
    ,L2 AS (SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B) -- 2^16 
    ,L3 AS (SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B) -- 2^32 
SELECT TOP 100000000 RAND(Checksum(NewId())) AS Val 
    INTO #T1 
    FROM L3; 

WITH x AS (
    SELECT Val,COUNT(*) Cnt 
    FROM #T1 
    GROUP BY Val 
) 
SELECT x.Cnt,COUNT(*)*1.0/(SELECT COUNT(*)/100 FROM #T1) Pct 
    FROM X 
GROUP BY x.Cnt; 

RAND() अकेले 6 घंटे से अधिक ले लिया और अंत में उत्पादन पंक्तियों की सही संख्या प्राप्त करने के लिए कई बार पुन: प्रारंभ करने के लिए किया था सेट आधारित पीढ़ी तो अनियमितता की तुलना के लिए आधारभूत पैदा करने के लिए बेकार है। यह भी लगता है कि यादृच्छिकता वांछित होने के लिए बहुत कुछ छोड़ देती है हालांकि यह प्रत्येक पंक्ति को संशोधित करने के लिए चेकसम (नया()) का उपयोग करने से बेहतर है।

Cnt Pct 
---- ---- 
1 99.768020 
2 00.115840 
3 00.000100 -- at least there were comparitively few values returned 3 times 

पुनरारंभ करने के कारण, निष्पादन समय पर कब्जा नहीं किया जा सका।

IF OBJECT_ID('tempdb..#T2') IS NOT NULL DROP TABLE #T2; 
GO 
CREATE TABLE #T2 (Val FLOAT); 
GO 
SET NOCOUNT ON; 
GO 
INSERT INTO #T2(Val) VALUES(RAND()); 
GO 100000000 

WITH x AS (
    SELECT Val,COUNT(*) Cnt 
    FROM #T2 
    GROUP BY Val 
) 
SELECT x.Cnt,COUNT(*)*1.0/(SELECT COUNT(*)/100 FROM #T2) Pct 
    FROM X 
GROUP BY x.Cnt; 
+0

पीएस यह सोचकर कि पुनरारंभ करने वाले कुछ डुप्लीकेट्स के लिए जिम्मेदार हो सकते थे, मैंने तुरंत 3 एम पंक्तियों का परीक्षण किया जो लगभग 6-1/2 मिनट लग गए। मुझे 2101 डुप्लिकेट मिले और 2 मान क्रमशः 3 गुना (.07% और .000067%) दिखाई दिए, जो संकेत देते हैं कि पुनरारंभ संभवतः एक हिस्सा खेला जाता है लेकिन यादृच्छिकता अभी भी तारकीय से दूर है। – bielawski

+0

एक अन्य उत्तर को ध्यान में रखते हुए सिर्फ नए लोगों के साथ विविधता में परिवर्तित किया गया, इसलिए मैंने भी कोशिश की। न केवल चेकसम का उपयोग करने से कोई तेज़ नहीं है बल्कि उस परीक्षण में एक मान 8 गुना दिखाई देता है। निष्पक्ष होने के लिए, यह अभी भी 95.44731 9% अद्वितीय था जो कि मेरे परीक्षण में केवल रैंड (चेकसम (न्यूआईडी())) की 95.450254% से भी बदतर है। एक दूसरे निष्पादन ने 100 एम पंक्तियों का परीक्षण करते समय भी 5 बार और 95.452929% अलग-अलग वाईएमएमवी दिखाई देने वाले 3 नंबरों का सबसे खराब मामला उत्पन्न किया। – bielawski

0
require_once('db/connect.php'); 

//rand(1000000 , 9999999); 

$products_query = "SELECT id FROM products"; 
$products_result = mysqli_query($conn, $products_query); 
$products_row = mysqli_fetch_array($products_result); 
$ids_array = []; 

do 
{ 
    array_push($ids_array, $products_row['id']); 
} 
while($products_row = mysqli_fetch_array($products_result)); 

/* 
echo '<pre>'; 
print_r($ids_array); 
echo '</pre>'; 
*/ 
$row_counter = count($ids_array); 

for ($i=0; $i < $row_counter; $i++) 
{ 
    $current_row = $ids_array[$i]; 
    $rand = rand(1000000 , 9999999); 
    mysqli_query($conn , "UPDATE products SET code='$rand' WHERE id='$current_row'"); 
} 
+0

शायद यह सही और आसान तरीका नहीं है लेकिन यह काम करता है))) – user3351200

संबंधित मुद्दे