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

SQL सर्वर सशर्त प्रवाह

मैं परीक्षण को

. के रूप में फिर से लिखूंगा
IF CASE
     WHEN EXISTS (SELECT ...) THEN CASE
                                   WHEN EXISTS (SELECT ...) THEN 1
                                 END
   END = 1  

जैसा कि यहां बताया गया है, यह शॉर्ट सर्किटिंग की गारंटी देता है, लेकिन इसका मतलब यह है कि आपको इसे ऑप्टिमाइज़र पर छोड़ने के बजाय सामने वाले का मूल्यांकन करने के लिए सबसे सस्ता चुनना होगा।

नीचे दिए गए मेरे अत्यंत सीमित परीक्षणों में परीक्षण करते समय निम्नलिखित सही प्रतीत हुए

<एच3>1. EXISTS AND EXISTS

EXISTS AND EXISTS संस्करण सबसे अधिक समस्याग्रस्त लगता है। यह जंजीर एक साथ कुछ बाहरी अर्ध जुड़ती है। किसी भी मामले में यह परीक्षण के क्रम को फिर से व्यवस्थित करने की कोशिश नहीं करता है और सस्ता पहले करता है (इस ब्लॉग पोस्ट के दूसरे भाग में चर्चा की गई एक समस्या)। IF ... . में अगर इसमें शॉर्ट सर्किट नहीं होता तो इससे कोई फर्क नहीं पड़ता। हालाँकि जब इस संयुक्त विधेय को WHERE . में रखा जाता है खंड योजना में परिवर्तन होता है और यह करता है शॉर्ट सर्किट ताकि पुनर्व्यवस्था फायदेमंद हो सके।

/*All tests are testing "If False And False"*/

IF EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=2)  
AND EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)=1)
PRINT 'Y'
/*
Table 'spt_values'. Scan count 1, logical reads 9
Table 'spt_monitor'. Scan count 1, logical reads 1
*/

IF EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)=1) 
AND EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=2) 
PRINT 'Y'
/*
Table 'spt_monitor'. Scan count 1, logical reads 1
Table 'spt_values'. Scan count 1, logical reads 9
*/

SELECT 1
WHERE  EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=2)  
AND EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)=1)
/*
Table 'Worktable'. Scan count 0, logical reads 0
Table 'spt_monitor'. Scan count 1, logical reads 1
*/

SELECT 1
WHERE  EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)=1) 
AND EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=2) 
/*
Table 'Worktable'. Scan count 0, logical reads 0
Table 'spt_values'. Scan count 1, logical reads 9

*/

इन सभी के लिए योजनाएँ बहुत समान दिखाई देती हैं। SELECT 1 WHERE ... . के बीच व्यवहार में अंतर का कारण संस्करण और IF ... संस्करण यह है कि पूर्व के लिए यदि स्थिति गलत है तो सही व्यवहार कोई परिणाम नहीं लौटाना है, इसलिए यह केवल OUTER SEMI JOINS को जंजीर देता है और यदि कोई गलत है तो शून्य पंक्तियाँ अगली पंक्ति तक ले जाती हैं।

हालांकि IF संस्करण हमेशा 1 या शून्य का परिणाम वापस करने की आवश्यकता है। यह योजना अपने बाहरी जोड़ में एक जांच कॉलम का उपयोग करती है और इसे गलत पर सेट करती है यदि EXISTS परीक्षण पारित नहीं किया गया है (केवल पंक्ति को त्यागने के बजाय)। इसका मतलब है कि अगले जॉइन में हमेशा 1 पंक्ति फीडिंग होती है और इसे हमेशा निष्पादित किया जाता है।

CASE संस्करण की एक समान योजना है लेकिन यह एक PASSTHRU . का उपयोग करता है भविष्यवाणी करें कि यह जॉइन के निष्पादन को छोड़ने के लिए उपयोग करता है यदि पिछला THEN शर्त पूरी नहीं हुई। मुझे यकीन नहीं है कि क्यों संयुक्त AND s समान दृष्टिकोण का उपयोग नहीं करेंगे।

<एच3>2. EXISTS OR EXISTS

EXISTS OR EXISTS संस्करण में एक संयोजन का उपयोग किया गया था (UNION ALL ) ऑपरेटर बाहरी सेमी जॉइन के आंतरिक इनपुट के रूप में। इस व्यवस्था का मतलब है कि जैसे ही पहला लौटाया जाता है, यह आंतरिक पक्ष से पंक्तियों का अनुरोध करना बंद कर सकता है (यानी यह प्रभावी रूप से शॉर्ट सर्किट कर सकता है) सभी 4 प्रश्न उसी योजना के साथ समाप्त हो गए जहां सस्ता विधेय का मूल्यांकन पहले किया गया था।

/*All tests are testing "If True Or True"*/

IF EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=1)  
OR EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)<>1)
PRINT 'Y'
/*
Table 'Worktable'. Scan count 0, logical reads 0
Table 'spt_monitor'. Scan count 1, logical reads 1
*/

IF EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)<>1) 
OR EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)= 1) 
PRINT 'Y'
/*
Table 'Worktable'. Scan count 0, logical reads 0
Table 'spt_monitor'. Scan count 1, logical reads 1
*/

SELECT 1
WHERE  EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)= 1)  
OR EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)<>1)
/*
Table 'Worktable'. Scan count 0, logical reads 0
Table 'spt_monitor'. Scan count 1, logical reads 1
*/

SELECT 1
WHERE  EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)<>1) 
OR EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=1) 
/*
Table 'Worktable'. Scan count 0, logical reads 0
Table 'spt_monitor'. Scan count 1, logical reads 1
*/
<एच3>3. एक ELSE जोड़ना

मेरे साथ ऐसा हुआ कि मैं AND . को परिवर्तित करने के लिए डी मॉर्गन के नियम का प्रयास कर रहा था करने के लिए OR और देखें कि क्या इससे कोई फर्क पड़ता है। पहली क्वेरी को परिवर्तित करने से देता है

IF NOT ((NOT EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=2)  
OR NOT EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)=1)))
PRINT 'Y'
ELSE
PRINT 'N'
/*
Table 'spt_monitor'. Scan count 1, logical reads 1
Table 'spt_values'. Scan count 1, logical reads 9
*/

तो यह अभी भी शॉर्ट सर्किटिंग व्यवहार पर कोई फर्क नहीं पड़ता है। हालांकि अगर आप NOT . को हटाते हैं और IF ... ELSE . के क्रम को उलट दें शर्तें यह अब करता है शॉर्ट सर्किट!

IF (NOT EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=2)  
OR NOT EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)=1))
PRINT 'N'
ELSE
PRINT 'Y'
/*
Table 'Worktable'. Scan count 0, logical reads 0
Table 'spt_monitor'. Scan count 1, logical reads 1
*/


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. कुछ क्षेत्रों में डुप्लीकेट खोजने के लिए कथन का चयन करें

  2. SQL सर्वर रिपोर्टिंग सेवाओं को ट्यून करना

  3. SQL सर्वर में रिस्टोरिंग मोड से डेटाबेस को ऑनलाइन कैसे करें

  4. SQL सर्वर में INNER JOIN का उपयोग करके मैं एकाधिक तालिकाओं से कैसे हटाऊं?

  5. SQL Server 2008 और SQL Server 2008 R2 चलाने वाले उपयोगकर्ता ध्यान दें