2008-11-28 15 views
6

के खंड में वर्तमान दिनांक की जांच करने का सबसे अच्छा तरीका मैं वर्तमान दिनांक के लिए दिनांक फ़ील्ड को चेक करने के लिए सबसे कुशल (सर्वोत्तम प्रदर्शन) तरीका खोजने का प्रयास कर रहा हूं। वर्तमान में हम इसका उपयोग कर रहे हैं:एसक्यूएल क्वेरी

SELECT  COUNT(Job) AS Jobs 
FROM   dbo.Job 
WHERE  (Received BETWEEN DATEADD(d, DATEDIFF(d, 0, GETDATE()), 0) 
         AND DATEADD(d, DATEDIFF(d, 0, GETDATE()), 1)) 
+3

कृपया ध्यान दें कि आपके द्वारा चुने गए उत्तर का सबसे अच्छा प्रदर्शन तरीका नहीं है।आपका रास्ता सही तरीके से करीब है, आपको बस BETWEEN का उपयोग करने के बजाय> = और <पर स्विच करने की आवश्यकता है (जो दूसरी स्थिति पर <= जैसा है और गलत है)। – ErikE

उत्तर

10
WHERE 
    DateDiff(d, Received, GETDATE()) = 0 

संपादित करें: के रूप में यह जवाब देने के लिए टिप्पणी में बाहर खड़े, कि एक आदर्श समाधान नहीं है। इस धागे में भी अन्य उत्तरों की जांच करें।

+2

मैं ऐसा नहीं करता, क्योंकि यह सार्ज सक्षम नहीं है। –

+0

@ मिच गेहूं: जब तक केवल तारीख भाग के साथ कोई कॉलम नहीं होता है और उस पर एक सूचकांक, तब तक आप कुछ भी नहीं कर सकते हैं वैसे भी। – Tomalak

+1

तोमालाक, नहीं - उसका प्रारंभिक समाधान सार्जेबल है ... जहां प्राप्त हुआ> = {मध्यरात्रि आज सुबह} और प्राप्त हुआ <{आधी रात आज रात} SARGable –

0

जो इसे करने का सबसे अच्छा तरीका है। आप DATEADD (डी, DATEDIFF (डी, 0, GETDATE()), 0) और DATEADD (डी, DATEDIFF (डी, 0, GETDATE()), 1) चर में डाल सकते हैं और इसके बजाय उन का उपयोग कर सकते हैं लेकिन मैं ' टी लगता है कि यह प्रदर्शन में सुधार होगा।

8

यदि आप केवल उन सभी रिकॉर्ड्स को ढूंढना चाहते हैं जहां प्राप्त तिथि आज है, और भविष्य में प्राप्त तिथियों के साथ रिकॉर्ड हैं, तो आप जो कर रहे हैं वह बहुत ही गलत है ... क्योंकि ऑपरेटर के बीच ऑपरेटर अनुमति देता है मूल्य जो समाप्ति सीमा के बराबर हैं, इसलिए आप प्राप्त तिथि = मध्यरात्रि के साथ रिकॉर्ड प्राप्त कर सकते हैं ...

यदि प्राप्त किए गए इंडेक्स का उपयोग करने की कोई आवश्यकता नहीं है, तो आपको केवल यह जांचना होगा कि वर्तमान दिनांक के साथ तारीख diff 0 है ...

Where DateDiff(day, received, getdate()) = 0 

यह विधेय SARGable नहीं निश्चित रूप से है, इसलिए यह एक सूचकांक का उपयोग नहीं कर सकते हैं ... 0,123,इसलिए इस क्वेरी के लिए एक मुद्दा है तो, यह मानते हुए कि आप भविष्य में दिनांक प्राप्त हुआ है नहीं कर सकते हैं, मैं इस का प्रयोग करेंगे बजाय ...

Where Received >= DateAdd(day, DateDiff(Day, 0, getDate()), 0) 

प्राप्त दिनांकों भविष्य में हो सकता है, तो आप शायद के रूप में कर रहे हैं सबसे कुशल के पास तुम हो सकता है के रूप में ... (सिवाय एक के बीच बदलने के> = और <)

+0

चार्ल्स, इंडेक्स के बिना भी, 'डेटडिफ (दिन, प्राप्त, getdate())' सबसे अच्छा नहीं है क्योंकि यह किसी भी कारण से अधिक CPU का उपयोग करके तालिका में प्रत्येक पंक्ति पर गणना को बल देता है। – ErikE

+0

@Emtucifor, सच है, लेकिन डिस्क I/O के साथ तुलना की जाती है, सीपीयू चक्र अप्रचलित होने के लिए बहुत महत्वहीन होते हैं। हम यहाँ परिमाण के तीन से चार आदेशों के बारे में बात कर रहे हैं। –

+0

यह सच है, चार्ल्स। परिप्रेक्ष्य में मेरी नाइटपिकिंग डालने के लिए धन्यवाद। :) मुझे लगता है कि जहां संभव हो वहां बाद वाले को अनुशंसा करना सबसे अच्छा है क्योंकि जब कोई अनुक्रमणिका होती है, तो इससे गंभीरता से I/O प्रभावित हो जाएगा। – ErikE

0

मुझे यकीन नहीं है कि आप "सर्वश्रेष्ठ" को परिभाषित कैसे कर रहे हैं लेकिन यह ठीक काम करेगा।

हालांकि, यदि यह क्वेरी कुछ है जो आप बार-बार चलाने जा रहे हैं तो आपको get_date() फ़ंक्शन से छुटकारा पाना चाहिए और वहां जो भी प्रोग्रामिंग भाषा आप इसे चला रहे हैं, उसके माध्यम से वहां एक शाब्दिक तिथि मान छूएं। उत्पादन हर 24 घंटों में केवल एक बार बदलता है, get_date(), current_date(), आदि गैर-निर्धारिती फ़ंक्शंस हैं, जिसका अर्थ है कि आपका आरडीएमएस संभवतः क्वेरी को अपने क्वेरी कैश में संग्रहीत करने के लिए उम्मीदवार के रूप में अमान्य कर देगा यदि उसके पास है।

0

कैसे 'मुक्केबाज़ी

WHERE 
     DATEDIFF(d, Received, GETDATE()) = 0 
+0

यह सबसे अच्छा तरीका नहीं है। सबसे अच्छा तरीका के लिए मार्क ग्रेवेल की पोस्ट देखें। – ErikE

0

मैं सामान्य रूप से solution suggested by Tomalak का प्रयोग करेंगे, लेकिन यदि आप प्रदर्शन के लिए वास्तव में हताश हैं सबसे अच्छा विकल्प एक अतिरिक्त अनुक्रमित क्षेत्र ReceivedDataPartOnly जोड़ने के लिए हो सकता है - जो समय हिस्सा बिना डाटा स्टोर होगा और उसके बाद क्वेरी

declare @today as datetime 
set @today = datediff(d, 0, getdate()) 

select  
    count(job) as jobs 
from   
    dbo.job 
where  
    received_DatePartOnly = @today 
+0

टॉमलाक द्वारा सुझाए गए समाधान सबसे अच्छे तरीके से दूर हैं। – ErikE

5

का उपयोग किसी भी सीपीयू आदि प्रति पंक्ति के बिना आप प्रदर्शन चाहते हैं, आप सूचकांक पर एक प्रत्यक्ष हिट चाहते हैं,; इस प्रकार, मैं पहले श्रेणी की गणना करता हूं, और उसके बाद एक सरल WHERE क्वेरी का उपयोग करता हूं। मुझे नहीं पता कि आप किस डीबी का उपयोग कर रहे हैं, लेकिन SQL सर्वर में, निम्न कार्य करता है:

// ... where @When is the date-and-time we have (perhaps from GETDATE()) 
DECLARE @DayStart datetime, @DayEnd datetime 
SET @DayStart = CAST(FLOOR(CAST(@When as float)) as datetime) -- get day only 
SET @DayEnd = DATEADD(d, 1, @DayStart) 

SELECT  COUNT(Job) AS Jobs 
FROM   dbo.Job 
WHERE  (Received >= @DayStart AND Received < @DayEnd) 
+0

मुझे यकीन नहीं है कि इंडेक्स पर "प्रत्यक्ष" हिट से आपका क्या मतलब है? यदि आप किसी अनुमानित ऑपरेटर के "अन्य" पक्ष पर गणना करते समय बस बात कर रहे हैं, तो इंडेक्स को निष्पादित करने से पहले इसे पूर्व-गणना करने के बजाय, या तो ए) गणना मूल्य तालिका में किसी अन्य कॉलम पर आधारित होता है और जेनरेट की गई पंक्ति के लिए समान नहीं है, इसलिए इसे एसक्यूएल में होना चाहिए, या बी) यदि यह प्रत्येक जेनरेट की गई पंक्ति के लिए समान मान है, तो क्वेरी प्रोसेसर वैसे भी इसकी गणना करेगा, इसलिए इसे केवल एक बार गणना की जाएगी, नहीं इससे कोई फर्क नहीं पड़ता कि क्वेरी कितनी पंक्तियां उत्पन्न करती है। –

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