2016-09-05 25 views
9

मैं घंटों के लिए नीचे दिए गए बयान डिबगिंग किया गया है:अजीब व्यवहार - यादृच्छिक चयन

SELECT 
(
SELECT t1.anotherColumn 
FROM table1 t1 
WHERE t1.aColumn=(1+ABS(Checksum(NewId()))%54) 
) res, * 
FROM 
(
SELECT TOP 200 * --PLEASE NOTICE HERE 
FROM table2 
)RESULT 

और समस्या यह है कि हमेशा res प्रत्येक पंक्ति के लिए एक ही मूल्य होता है। अब, अगर मैं 200 बदलता हूं जो 176 से नीचे किसी भी संख्या में क्वेरी कथन में हाइलाइट किया गया है तो यह table1 की यादृच्छिक पंक्तियां दिखाता है जो वांछित परिणाम है!
कृपया ध्यान दें कि 54 के परिणामों पर कोई प्रभाव नहीं पड़ता है और यह केवल इसलिए है क्योंकि मेरी तालिका में aColumn के लिए 1 से 54 के 54 अलग-अलग मान हैं।
मैंने इस क्वेरी को विभिन्न तालिकाओं पर आजमाया है और यह अजीब व्यवहार दोहराया गया है!

+0

ऐसा लगता है कि क्वेरी ऑप्टिमाइज़र यहां काम पर है। –

+0

@TimBiegeleisen यह सीम करता है कि SQL सर्वर दृश्य के पीछे कुछ कर रहा है, और हो सकता है कि वह क्वेरी ऑप्टिमाइज़र है, मुझे यकीन नहीं है कि जब तक आप किसी भी तरह से नहीं जानते। बीटीडब्ल्यू, धन्यवाद देने का एक तरीका होना चाहिए कृपया मेरे लिए यह मत करो! – mok

+0

आपको प्रत्येक परिणाम पंक्ति के लिए पहले सबक्वायरी निष्पादित करने के लिए इंजन को मजबूर करने की आवश्यकता हो सकती है। पहले सबक्वायरी में एक डमी स्थिति जोड़ने का प्रयास करें जो इसे एक सहसंबंध क्वेरी बनाता है, जैसे 'और result.id शून्य नहीं है – trincot

उत्तर

4

परिणामों में अंतर क्वेरी योजनाओं में मतभेदों द्वारा समझाया जा सकता है।

एसक्यूएल ऑप्टिमाइज़र टेबल स्पूल/आलसी स्पूल ऑपरेटर का उपयोग करना चुन सकता है। इस मामले में, NEWID() को एक बार बुलाया जाता है, GUID temp तालिका में संग्रहीत होता है और अन्य सभी पंक्तियों के लिए उपयोग किया जाता है।

https://technet.microsoft.com/en-us/library/ms191221(v=sql.105).aspx

... अद्यतन: क्वेरी योजना तल पर रेखा से नीचे जोड़कर तय किया जा सकता है:,

option(use plan 
N' 
<your XML plan> 
') 

को पकड़ने के लिए "अच्छा" एक्सएमएल योजना चलाने

SET SHOWPLAN_XML ON 

और क्वेरी को निष्पादित करें जो अपेक्षित परिणाम दिखाता है। यह विकल्प को कॉपी-पेस्ट (उपयोग योजना ...)

यह समाधान पंक्तियों की बड़ी संख्या (लाखों)

+0

मुझे समाधान (GETDATE()> '2011-01-01') को अस्थायी रूप से निकालना पड़ा क्योंकि यह हमेशा काम नहीं करता है जब आप बहुत सारे रिकॉर्ड (हजारों) पूल करते हैं और जब आपके पास टेबल 1 में हजारों पंक्तियां होती हैं। यदि कल भी इसकी आवश्यकता है तो मैं कल एक और प्रदान करूंगा। यह वास्तव में पंक्तियों की संख्या पर निर्भर करता है, इसलिए यदि आपकी तालिका छोटी है, तो भी आप इसका उपयोग कर सकते हैं। – Anton

+0

धन्यवाद। कम से कम अब मुझे समस्या की जड़ पता है। मैं कल इसे काम करने की कोशिश करूंगा क्योंकि हां कभी-कभी टेबल बहुत बड़ा हो जाता है। – mok

+0

एक क्वेरी योजना को ठीक करने के लिए, आप "अच्छी" योजना को सहेज सकते हैं, और उसके बाद "उपयोग योजना" क्वेरी संकेत के साथ फिर से उपयोग कर सकते हैं। https://technet.microsoft.com/en-us/library/ms186954(v=sql.105).aspx – Anton

2

यह सबक्वेरी हर पंक्ति पर reevaulated जा करने के लिए बाध्य करेगा के लिए मेरे लिए काम करता है और जटिल से बचा जाता है यादृच्छिक तर्क।

SELECT top 200 
    (SELECT top 1 t1.anotherColumn from table1 t1 with(nolock) where t2.t2Id is not null order by newid() ) res, 
    * 
FROM table2 t2 

यह काम करता है क्योंकि newid() पहले से ही एक यादृच्छिक अद्वितीय पहचानकर्ता और table2 बलों table1 की प्रत्येक पंक्ति table2 में पंक्ति में उसकी जांच की पर तुलना है।

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