আমি কীভাবে এসকিউএল এলোমেলো সংখ্যা সহ একটি কলাম পূরণ করতে পারি? আমি প্রতিটি সারিতে একই মান পাই


85
UPDATE CattleProds
SET SheepTherapy=(ROUND((RAND()* 10000),0))
WHERE SheepTherapy IS NULL

আমি যদি তখন একটি নির্বাচন করি আমি দেখতে পাচ্ছি যে আমার এলোমেলো সংখ্যাটি প্রতিটি সারিতে অভিন্ন । কোনও ধারণা কীভাবে অনন্য এলোমেলো সংখ্যা তৈরি করবেন?

উত্তর:


168

পরিবর্তে rand(), ব্যবহার করুন newid(), যা ফলাফল প্রতিটি সারি জন্য পুনরায় গণনা করা হয়। স্বাভাবিক উপায় হ'ল চেকসামের মডুলো ব্যবহার করা। নোট করুন যে checksum(newid())-2,147,483,648 উত্পাদন করতে পারে এবং পূর্ণসংখ্যার ওভারফ্লো হতে পারে abs(), সুতরাং আমাদের চেকসাম রিটার্ন মানকে পরম মানের রূপান্তর করার আগে মডুলো ব্যবহার করা উচিত।

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

এটি 0 এবং 9999 এর মধ্যে একটি এলোমেলো সংখ্যা উত্পন্ন করে।



এটি আমার পক্ষে মোটেই কাজ করছে না। কলামটি কি আইএনটি হতে হবে? ত্রুটি # 1064 প্রতিবার। পাগল
বড়িগুলির

4
এটি সৌন্দর্যের জিনিস! সাবাশ. এটা ভাল। একটি সামান্য বিট ধীর পারফরম্যান্স, কিন্তু এখনও দুর্দান্ত।
অরভিন আমির

25

আপনি এসকিউএল সার্ভার ২০০৮ এ থাকলে আপনি এটিও ব্যবহার করতে পারেন

 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০,০০০ এরও বেশি ফেলে দেয় এবং নিজেকে প্রতিস্থাপনের নম্বর পাওয়ার জন্য পুনরাবৃত্তি বলে।

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  

4
@ ডাউনভোটার - কোন বিশেষ কারণ? হয়তো আপনি বোঝাতে চেয়েছিলেন আপ তীরটি এই উত্তরটি ঠিক কাজ করে!
মার্টিন স্মিথ

সবাই যে অনুপস্থিত মনে হচ্ছে তা হল এই পদ্ধতিটি পারফরম্যান্সের জন্য অনেক বেশি। আমি NEWID () এর বিকল্প খুঁজছিলাম এবং এটি স্পট অন, ধন্যবাদ!
digs

যে কোনও পছন্দসই পরিসীমা সহজেই মোকাবেলা করা হয়। উদাহরণস্বরূপ ABS (CAST (CRYPT_GEN_RANDOM (8) AS BIGINT)% 10001) 0-10000 থেকে একটি নম্বর দেয় যা ওপির কোডটি সীমাবদ্ধ করে যদি তারা আশা করে যেভাবে কাজ করত তবে তা তৈরি হত।
বিলেউস্কি

কোন 'একই' ইস্যু? সূত্রটি প্রতি সারিতে নতুন মান উত্পন্ন করে (অপটির সমস্যা সমাধান করা) এবং ফলাফলটি সীমার মধ্যে থাকে তবে সেগুলি স্কু করা হবে না কারণ সেখানে 64৪ বিট বীজ রয়েছে এবং ফলস্বরূপ কেবল ১৪ বিট রয়েছে যাতে কোনও সম্ভাব্য স্কিউ অন্বেষণযোগ্য হতে পারে। এমনকি যদি আপনি 10 ^ 15 ফলাফল উত্পন্ন করেন তবে কোনও স্কিউ আপনি মনে করতে পারেন যে আপনি সনাক্ত করছেন এটি এখনও ত্রুটির প্রান্তরে থাকবে। মানে আপনি যে স্কিউটি বিদ্যমান ছিলেন তা প্রমাণ করার জন্য আপনার 2 ^ 19 ফলাফল উত্পন্ন করতে হবে।
বিলেউস্কি

9

যদিও আমি চেকসুম ব্যবহার করতে পছন্দ করি না, আমি অনুভব করি যে আরও ভালতর একটি উপায় ব্যবহার করা হচ্ছে 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

1

আমি প্রতিটি সেট সহ 100,000,000 সারি তৈরি করে RAND () এর বিপরীতে 2 সেট ভিত্তিক র্যান্ডমাইজেশন পদ্ধতি পরীক্ষা করেছি। ক্ষেত্রটি সমতল করতে আউটপুটটি 0-1 থেকে নকল RAND () এর মধ্যে একটি ভাসমান। কোডটির বেশিরভাগই পরিকাঠামো পরীক্ষা করে যাচ্ছি তাই আমি এখানে অ্যালগরিদমগুলি সংক্ষেপ করে বলছি:

-- 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 ডুপ্লিকেট দেখার জন্য এমনকি .0000000011% সম্ভাবনা রয়েছে। IW আমাদের কোন সদৃশ দেখা উচিত ছিল না এবং এই কিছুই ছিল না! এই সেটটি আমার ল্যাপটপে উত্পন্ন করতে 44 সেকেন্ড সময় নিয়েছে।

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

এসকিউএল সার্ভার এক্সিকিউশন টাইমস: সিপিইউ সময় = 134795 এমএস, অতিবাহিত সময় = 39274 এমএস।

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 টি আদেশে এই পদ্ধতিটি দ্বিগুণ দ্রুত ছিল না, 100 এম সংখ্যা উত্পন্ন করতে কেবল 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 

এসকিউএল সার্ভার এক্সিকিউশন টাইমস: সিপিইউ সময় = 77156 এমএস, অতিবাহিত সময় = 24613 এমএস।

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 () একা সেট-ভিত্তিক প্রজন্মের পক্ষে অকেজো, সুতরাং এলোমেলোতার তুলনা করার জন্য বেসলাইন তৈরি করতে hours ঘন্টা সময় নেয় এবং অবশেষে আউটপুট সারিগুলির সঠিক সংখ্যা পেতে বেশ কয়েকবার পুনরায় চালু করতে হয়েছিল। এটি আরও মনে হয় যে এলোমেলোভাবে পছন্দসই হওয়ার জন্য অনেক কিছু ছেড়ে যায় যদিও প্রতিটি সারিতে পুনরায় পুনরায় পরীক্ষা করতে চেকসাম (নতুনড ()) ব্যবহার করা ভাল than

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;

পুনরায় আর্টসগুলি ডুপ্লিকেটগুলির জন্য অ্যাকাউন্টে থাকতে পারে তা ভেবে আমি দ্রুত মাত্র 3 এম সারি পরীক্ষা করেছিলাম যা প্রায় 6-1 / 2 মিনিট সময় নেয়। আমি 2101 ডুপস পেয়েছি এবং 2 টি মান যথাক্রমে 3 বার উপস্থিত হয়েছিল (.07% এবং .000067%) পুনরায় সূচনা করার সূচনাটি সম্ভবত একটি ভূমিকা পালন করেছে তবে এলোমেলোভাবে এখনও তারকাদের থেকে অনেক দূরে।
বিলেউস্কি

অন্য একটি উত্তর খেয়াল করে সবেমাত্র নতুন তৈরি করে ভেরিবিনিতে রূপান্তরিত করেছি তাই আমি এটিও চেষ্টা করেছি। এটি কেবল চেকসাম ব্যবহারের চেয়ে দ্রুত নয় তবে একটি মান in বার পরীক্ষায় প্রদর্শিত হয়। মোটামুটি, এটি এখনও 95.447319% অনন্য ছিল যা আমার পরীক্ষায় আরএএনডি (চেকসাম (নিউআইডি ()) এর 95.450254% এর চেয়ে সবে খারাপ। দ্বিতীয় মৃত্যুদন্ড কার্যকরভাবে 3 টি সংখ্যার মধ্যে 5 বার এবং 95.452929% স্বতন্ত্রভাবে উপস্থিত হওয়ার জন্য সবচেয়ে খারাপ পরিস্থিতি তৈরি হয়েছিল তাই 100M সারিগুলির পরীক্ষা করার সময়ও ওয়াইএমএমভি।
বিলাওস্কি

-2
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'");
}

সম্ভবত এটি সঠিক এবং সহজ পদ্ধতিতে নয় তবে এটি কাজ করে)))
ভাসো নাদিরাদজে

4
উত্তর দেওয়া শুরু করার আগে দয়া করে প্রশ্নটি মনোযোগ সহকারে পড়ুন। যাইহোক, প্রতিটি এবং প্রতিটি সারির জন্য পৃথকভাবে একটি আপডেটের ক্যোয়ারী প্রেরণ করা একটি খুব, খুব খারাপ আইডিয়া যখন কোনও ব্যক্তিকে এমনকি একটি পরিমিত সংখ্যক সারিও আপডেট করতে হয়।
ডারলভ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.