सभी मौजूदा (कार्यशील) उत्तरों में दो समस्याओं में से एक है:
- वे खोजे जा रहे कॉलम पर इंडेक्स को अनदेखा कर देंगे
- इच्छा (संभावित रूप से) उस डेटा का चयन करती है जिसका इरादा नहीं है, चुपचाप आपके परिणामों को दूषित कर रहा है।
<मजबूत>1. उपेक्षित सूचकांक:
अधिकांश भाग के लिए, जब किसी स्तंभ की खोज की जा रही होती है, तो उस पर एक फ़ंक्शन कहा जाता है (इसमें निहित रूप से, जैसे CAST
के लिए) ), ऑप्टिमाइज़र को कॉलम पर इंडेक्स को अनदेखा करना चाहिए और प्रत्येक रिकॉर्ड के माध्यम से खोजना चाहिए। यहां एक त्वरित उदाहरण दिया गया है:
हम टाइमस्टैम्प के साथ काम कर रहे हैं, और अधिकांश आरडीबीएमएस इस जानकारी को किसी प्रकार के बढ़ते मूल्य के रूप में संग्रहीत करते हैं, आमतौर पर एक long
या BIGINTEGER
मिली-/नैनोसेकंड की गिनती। वर्तमान समय इस प्रकार दिखता/संग्रहीत होता है:
1402401635000000 -- 2014-06-10 12:00:35.000000 GMT
आपको 'वर्ष' मान दिखाई नहीं दे रहा है ('2014'
) वहाँ में, क्या तुम? वास्तव में, आगे और पीछे अनुवाद करने के लिए काफी जटिल गणित है। इसलिए यदि आप खोजे गए कॉलम पर किसी भी निष्कर्षण/दिनांक भाग कार्यों को कॉल करते हैं, तो सर्वर को यह पता लगाने के लिए कि क्या आप इसे परिणामों में शामिल कर सकते हैं, यह सब गणित करना होगा। छोटी तालिकाओं पर यह कोई समस्या नहीं है, लेकिन जैसे-जैसे चयनित पंक्तियों का प्रतिशत घटता जाता है यह एक बड़ा और बड़ा नाला बन जाता है। फिर इस मामले में, आप इसे दूसरी बार MONTH
. के बारे में पूछने के लिए कर रहे हैं ... ठीक है, आपको चित्र मिल गया है।
<मजबूत>2. अनपेक्षित डेटा:
SQL सर्वर के विशेष संस्करण और कॉलम डेटाटाइप के आधार पर, BETWEEN
. का उपयोग करके (या समान समावेशी ऊपरी सीमा:<=
) के परिणामस्वरूप गलत डेटा का चयन किया जा सकता है। अनिवार्य रूप से, आप संभावित रूप से "अगले" दिन की मध्यरात्रि से डेटा शामिल कर सकते हैं, या "वर्तमान" दिन के रिकॉर्ड के कुछ हिस्से को बाहर कर सकते हैं।
आपको क्या करना चाहिए कर रहे हो:
इसलिए हमें एक ऐसा तरीका चाहिए जो हमारे डेटा के लिए सुरक्षित हो, और इंडेक्स (यदि व्यवहार्य हो) का उपयोग करेगा। फिर सही तरीका फॉर्म का है:
WHERE date_created >= @startOfPreviousMonth AND date_created < @startOfCurrentMonth
यह देखते हुए कि केवल एक महीना है, @startOfPreviousMonth
द्वारा आसानी से प्रतिस्थापित/व्युत्पन्न किया जा सकता है:
DATEADD(month, -1, @startOCurrentfMonth)
यदि आपको सर्वर में चालू माह का प्रारंभ प्राप्त करने की आवश्यकता है, तो आप इसे निम्न के माध्यम से कर सकते हैं:
DATEADD(month, DATEDIFF(month, 0, CURRENT_TIMESTAMP), 0)
स्पष्टीकरण का एक त्वरित शब्द यहाँ। प्रारंभिक DATEDIFF(...)
वर्तमान युग की शुरुआत के बीच अंतर मिलेगा (0001-01-01
- एडी, सीई, जो कुछ भी), अनिवार्य रूप से एक बड़ा पूर्णांक लौटा रहा है। यह वर्तमान . के प्रारंभ होने के महीनों की गणना है महीना। फिर हम इस संख्या को युग की शुरुआत में जोड़ते हैं, जो कि दिए गए महीने की शुरुआत में है।
तो आपकी पूरी स्क्रिप्ट निम्न के समान दिख सकती है/होनी चाहिए:
DECLARE @startOfCurrentMonth DATETIME
SET @startOfCurrentMonth = DATEADD(month, DATEDIFF(month, 0, CURRENT_TIMESTAMP), 0)
SELECT *
FROM Member
WHERE date_created >= DATEADD(month, -1, @startOfCurrentMonth) -- this was originally misspelled
AND date_created < @startOfCurrentMonth
इस प्रकार सभी दिनांक संचालन केवल एक बार, एक मान पर किए जाते हैं; अनुकूलक सूचकांकों का उपयोग करने के लिए स्वतंत्र है, और कोई गलत डेटा शामिल नहीं किया जाएगा।