Sqlserver
 sql >> डेटाबेस >  >> RDS >> Sqlserver

टी-एसक्यूएल में यादृच्छिक भारित विकल्प

डेन के जवाब में एक वर्ग कानून पेश करने वाले तरीके से स्वयं शामिल होता है। (n*n/2) शामिल होने के बाद पंक्तियाँ जहाँ तालिका में n पंक्तियाँ हैं।

तालिका को केवल एक बार पार्स करने में सक्षम होने के लिए और अधिक आदर्श क्या होगा।

DECLARE @id int, @weight_sum int, @weight_point int
DECLARE @table TABLE (id int, weight int)

INSERT INTO @table(id, weight) VALUES(1, 50)
INSERT INTO @table(id, weight) VALUES(2, 25)
INSERT INTO @table(id, weight) VALUES(3, 25)

SELECT @weight_sum = SUM(weight)
FROM @table

SELECT @weight_point = FLOOR(((@weight_sum - 1) * RAND() + 1))

SELECT
    @id = CASE WHEN @weight_point < 0 THEN @id ELSE [table].id END,
    @weight_point = @weight_point - [table].weight
FROM
    @table [table]
ORDER BY
    [table].Weight DESC

यह @id . को सेट करते हुए तालिका के माध्यम से जाएगा प्रत्येक रिकॉर्ड के id . के लिए एक ही समय में @weight . को घटाते हुए मान बिंदु। आखिरकार, @weight_point नकारात्मक जाएगा। इसका मतलब है कि SUM सभी पूर्ववर्ती भारों में से यादृच्छिक रूप से चुने गए लक्ष्य मान से अधिक है। यह वह रिकॉर्ड है जो हम चाहते हैं, इसलिए उस बिंदु से हम @id . सेट करते हैं स्वयं के लिए (तालिका में किसी भी आईडी को अनदेखा करना)।

यह केवल एक बार तालिका के माध्यम से चलता है, लेकिन पूरी तालिका के माध्यम से चलना पड़ता है, भले ही चुना गया मान पहला रिकॉर्ड हो। क्योंकि औसत स्थिति तालिका से आधी दूरी पर है (और बढ़ते वजन के आधार पर कम होने पर) लूप लिखना संभवतः तेज़ हो सकता है... (विशेषकर यदि भार सामान्य समूहों में हों):

DECLARE @id int, @weight_sum int, @weight_point int, @next_weight int, @row_count int
DECLARE @table TABLE (id int, weight int)

INSERT INTO @table(id, weight) VALUES(1, 50)
INSERT INTO @table(id, weight) VALUES(2, 25)
INSERT INTO @table(id, weight) VALUES(3, 25)

SELECT @weight_sum = SUM(weight)
FROM @table

SELECT @weight_point = ROUND(((@weight_sum - 1) * RAND() + 1), 0)

SELECT @next_weight = MAX(weight) FROM @table
SELECT @row_count   = COUNT(*)    FROM @table WHERE weight = @next_weight
SET @weight_point = @weight_point - (@next_weight * @row_count)

WHILE (@weight_point > 0)
BEGIN
    SELECT @next_weight = MAX(weight) FROM @table WHERE weight < @next_weight
    SELECT @row_count   = COUNT(*)    FROM @table WHERE weight = @next_weight
    SET @weight_point = @weight_point - (@next_weight * @row_count)
END

-- # Once the @weight_point is less than 0, we know that the randomly chosen record
-- # is in the group of records WHERE [table].weight = @next_weight

SELECT @row_count = FLOOR(((@row_count - 1) * RAND() + 1))

SELECT
    @id = CASE WHEN @row_count < 0 THEN @id ELSE [table].id END,
    @row_count = @row_count - 1
FROM
    @table [table]
WHERE
    [table].weight = @next_weight
ORDER BY
    [table].Weight DESC


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Azure SQL DB घोषणा (पूर्वावलोकन) के लिए स्पॉटलाइट क्लाउड समर्थन

  2. SQL सर्वर में मिनटों में समय अंतर की गणना करें

  3. एक अजीब त्रुटि प्राप्त करना, SQL सर्वर क्वेरी `विथ` क्लॉज का उपयोग कर

  4. चयन सूची में कहीं और एक उपनाम का संदर्भ लें

  5. एक कंप्यूटेड कॉलम बनाएं जो SQL सर्वर में किसी अन्य तालिका से डेटा का उपयोग करता है