UPDATE CattleProds
SET SheepTherapy=(ROUND((RAND()* 10000),0))
WHERE SheepTherapy IS NULL
अगर मैं एक चयन करता हूं तो मैं देखता हूं कि मेरी यादृच्छिक संख्या हर पंक्ति में समान है । किसी भी विचार कैसे अद्वितीय यादृच्छिक संख्या उत्पन्न करने के लिए?
UPDATE CattleProds
SET SheepTherapy=(ROUND((RAND()* 10000),0))
WHERE SheepTherapy IS NULL
अगर मैं एक चयन करता हूं तो मैं देखता हूं कि मेरी यादृच्छिक संख्या हर पंक्ति में समान है । किसी भी विचार कैसे अद्वितीय यादृच्छिक संख्या उत्पन्न करने के लिए?
जवाबों:
इसके बजाय rand(), उपयोग करें newid(), जो परिणाम में प्रत्येक पंक्ति के लिए पुनर्गणना है। सामान्य तरीका चेकसम के मोडुलो का उपयोग करना है। ध्यान दें कि checksum(newid())-2,147,483,648 का उत्पादन कर सकते हैं और पूर्णांक अतिप्रवाह का कारण बन सकते हैं abs(), इसलिए हमें इसे पूर्ण मान में परिवर्तित करने से पहले चेकसम रिटर्न मान पर मॉडुलो का उपयोग करने की आवश्यकता है।
UPDATE CattleProds
SET SheepTherapy = abs(checksum(NewId()) % 10000)
WHERE SheepTherapy IS NULL
यह 0 और 9999 के बीच एक यादृच्छिक संख्या उत्पन्न करता है।
यदि आप SQL Server 2008 पर हैं, तो आप भी उपयोग कर सकते हैं
CRYPT_GEN_RANDOM(2) % 10000
जो कुछ हद तक सरल लगता है (यह प्रति पंक्ति के अनुसार एक बार मूल्यांकन किया जाता 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-65535 के बीच है जो 10,000 से समान रूप से विभाज्य नहीं है, कुछ संख्याओं का प्रतिनिधित्व थोड़ा अधिक होगा। इसका एक तरीका यह होगा कि इसे एक स्केलर यूडीएफ में लपेटा जाए जो किसी भी संख्या को 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
जबकि मुझे CHECKSUM का उपयोग करना पसंद है, मुझे लगता है कि जाने के लिए एक बेहतर तरीका उपयोग कर रहा है 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
मैंने प्रत्येक के साथ 100,000,000 पंक्तियों को उत्पन्न करके RAND () के खिलाफ 2 सेट आधारित यादृच्छिककरण विधियों का परीक्षण किया। फ़ील्ड को समतल करने के लिए आउटपुट रैंड (नकल) से 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 का उपयोग करना स्पष्ट रूप से सबसे यादृच्छिक था क्योंकि 10 ^ 18 नंबर के सेट से 10 ^ 8 नंबर को फेकने पर केवल 1 डुप्लिकेट देखने का केवल .000000001% मौका है। IOW हमें कोई डुप्लिकेट नहीं देखना चाहिए था और यह कोई भी नहीं था! इस सेट को मेरे लैपटॉप पर बनाने में 44 सेकंड का समय लगा।
Cnt Pct
----- ----
1 100.000000 --No duplicates
SQL सर्वर निष्पादन समय: CPU समय = 134795 ms, बीता समय = 39274 ms।
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 ऑर्डर कम यादृच्छिक रूप से यह विधि दो बार तेजी से नहीं थी, 100M संख्या उत्पन्न करने में केवल 23 सेकंड लगते हैं।
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
SQL सर्वर निष्पादन समय: CPU समय = 77156 ms, बीता समय = 24613 ms।
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;
रैंड () अकेले सेट-बेस्ड जेनरेशन के लिए बेकार है, इसलिए बेतरतीबपन की तुलना करने के लिए बेसलाइन तैयार करने में 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;
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'");
}