sql - जहां खंड में अजीब यादृच्छिक व्यवहार




oracle plsql (3)

मेरे पास इस तरह एक मेज है:

     Id | GroupId | Category
     ------------------------
     1  | 101     | A
     2  | 101     | B
     3  | 101     | C
     4  | 103     | B
     5  | 103     | D
     6  | 103     | A
     ........................

मुझे यादृच्छिक रूप से GroupId से एक को चुनना होगा इसके लिए मैंने निम्नलिखित पीएल / एसक्यूएल कोड ब्लॉक का प्रयोग किया है:

declare v_group_count number;
  v_group_id number;
begin 
  select count(distinct GroupId) into v_group_count from MyTable;
  SELECT GroupId into v_group_id  FROM
  (
    SELECT GroupId, ROWNUM RN FROM 
    (SELECT DISTINCT GroupId FROM MyTable)
  )
  WHERE RN=Round(dbms_random.value(1, v_group_count));
end;

क्योंकि मैं यादृच्छिक मूल्य को गोल करता हूं तो यह एक पूर्णांक मान होगा और WHERE RN=Round(dbms_random.value(1, v_group_count)) स्थिति को हमेशा एक पंक्ति वापस करना चाहिए आम तौर पर मुझे उम्मीद से एक पंक्ति देता है लेकिन अजीब कभी कभी यह मुझे कोई पंक्ति नहीं देता है और कभी-कभी यह दो पंक्तियां देता है यही कारण है कि यह इस खंड में त्रुटि देता है:

SELECT GroupId into v_group_id

कोई भी उस व्यवहार का कारण जानता है?


Answers

round(dbms_random.value(1, v_group_count)) को प्रत्येक पंक्ति में निष्पादित किया जा रहा है, इसलिए प्रत्येक पंक्ति का चयन किया जा सकता है या नहीं

पी.एस.

ROUND एक बुरा विकल्प है

किनारे के किसी भी मूल्य (जैसे 1 और 10) प्राप्त करने की संभावना किसी अन्य मूल्य (जैसे 2 से 9) प्राप्त करने की आधा संभावना है।
यह 0.0555 है ... (1/18) बनाम। 0.111 ... (1/ 9)

[  1,1.5) --> 1
[1.5,2.5) --> 2
.
.
.
[8.5,9.5) --> 9
[9.5, 10) --> 10
select          n,count(*)
from           (select          round(dbms_random.value(1, 10)) as n
                from            dual
                connect by      level <= 100000
                )
group by        n
order by        n
;
    N   COUNT(*)
    1   5488
    2   11239
    3   11236
    4   10981
    5   11205
    6   11114
    7   11211
    8   11048
    9   10959
    10  5519

मेरी सिफारिश DBMS_random.value (1, N + 1) पर FLOOR का उपयोग करना है

    select          n,count(*)
    from           (select          floor(dbms_random.value(1, 11)) as n
                    from            dual
                    connect by      level <= 100000
                    )
    group by        n
    order by        n   
    ;              
N   COUNT(*)
1   10091
2   10020
3   10020
4   10021
5   9908
6   10036
7   10054
8   9997
9   9846
10  10007              

यदि आप एक बेतरतीब ढंग से चयन करना चाहते हैं:

declare v_group_count number;
  v_group_id number;
begin 
  SELECT GroupId into v_group_id
  FROM (SELECT DISTINCT GroupId
        FROM MyTable
        ORDER BY dbms_random.value
       ) t
  WHERE rownum = 1
end;

उनके पास एक अलग मानव-पठनीय अर्थ है।

हालांकि, क्वेरी ऑप्टिमाइज़र के आधार पर, उनके पास मशीन के समान अर्थ हो सकता है।

आपको हमेशा पठनीय होने के लिए कोड होना चाहिए।

यही कहना है, यदि यह एक अंतर्निहित संबंध है, तो स्पष्ट शामिल होने का उपयोग करें। यदि आप कमजोर संबंधित डेटा से मेल खाते हैं, तो खंड कहां उपयोग करें।





sql oracle plsql