जवाबों:
चूँकि आप datetimeडेटाटाइप का उपयोग कर रहे हैं , आपको यह समझने की आवश्यकता है कि SQL सर्वर डेटाटाइम को कैसे राउंड करता है।
╔═══════════╦═════╦═════════════════════════════╦═════════════════════════════╦══════════╦═══════════╗
║ Name ║ sn ║ Minimum value ║ Maximum value ║ Accuracy ║ Storage ║
╠═══════════╬═════╬═════════════════════════════╬═════════════════════════════╬══════════╬═══════════╣
║ datetime ║ dt ║ 1753-01-01 00:00:00.000 ║ 9999-12-31 23:59:59.997 ║ 3.33 ms ║ 8 bytes ║
║ datetime2 ║ dt2 ║ 0001-01-01 00:00:00.0000000 ║ 9999-12-31 23:59:59.9999999 ║ 100ns ║ 6-8 bytes ║
╚═══════════╩═════╩═════════════════════════════╩═════════════════════════════╩══════════╩═══════════╝
नीचे क्वेरी का उपयोग करके, आप DATETIME
डेटा प्रकार का उपयोग करते समय आसानी से उस sql सर्वर को गोल करने की समस्या देख सकते हैं ।
select '2015-07-27 00:00:00.000' as Original_startDateTime,
convert(datetime ,'2015-07-27 00:00:00.000') as startDateTime,
'2015-07-27 23:59:59.999' as Original_endDateTime,
convert(datetime ,'2015-07-27 23:59:59.999') as endDateTime,
'2015-07-27 00:00:00.000' as Original_startDateTime2,
convert(datetime2 ,'2015-07-27 00:00:00.000') as startDateTime2, -- default precision is 7
'2015-07-27 23:59:59.999' as Original_endDateTime2,
convert(datetime2 ,'2015-07-27 23:59:59.999') as endDateTime2 -- default precision is 7
DATETIME2
SQL Server 2008 के बाद से चारों ओर है, इसलिए इसके बजाय इसका उपयोग करना शुरू करें DATETIME
। अपनी स्थिति के लिए, आप उपयोग कर सकते हैं datetime2
के साथ 3 दशमलव की परिशुद्धता जैसे datetime2(3)
।
उपयोग करने के लाभ datetime2
:
datetime
केवल 3 दशमलव स्थानों का समर्थन करता है .. और इसलिए आप गोल datetime
चक्कर को डिफ़ॉल्ट रूप से देखते हैं , या सेकंड के .003 seconds
वेतन वृद्धि के साथ निकटतम ।.000
.003
.007
datetime2
की तुलना में बहुत अधिक सटीक है datetime
और datetime2
आपको नियंत्रण देता है DATE
और इसके TIME
विपरीत datetime
।संदर्भ:
DateTime2
बनाम DateTime
: ए। के लिए - विशाल - बहुसंख्यक - का - वास्तविक - दुनिया का उपयोग करें - मामलों, DateTime2
ज्यादा <लागतों का लाभ । देखें: stackoverflow.com/questions/1334143/… b। यही कारण है कि नहीं है जड़ समस्या यहाँ। अगली टिप्पणी देखें
datetime3
70 (बनाम 7) के साथ सटीक जोड़ा गया अंक?)। सबसे अच्छा अभ्यास एक ऐसे मूल्य का उपयोग करना है जहां परिशुद्धता मायने नहीं रखती है, << अगले दूसरे की शुरुआत , मिनट, घंटे या दिन बनाम <= पहले दूसरे, मिनट, घंटे या दिन का अंत ।
जैसा कि कई अन्य लोगों ने टिप्पणियों में उल्लेख किया है और आपके प्रश्न के अन्य उत्तरों में मुख्य मुद्दा SQL सर्वर द्वारा 2015-07-27 23:59:59.999
गोल किया जा रहा है 2015-07-28 00:00:00.000
। प्रलेखन के लिए प्रतिDATETIME :
समय सीमा - 00:00:00 23: 59: 59.997 के माध्यम से
ध्यान दें कि समय सीमा कभी नहीं हो सकती .999
। प्रलेखन में और नीचे यह गोलाई नियमों को निर्दिष्ट करता है जो SQL सर्वर कम से कम महत्वपूर्ण अंक के लिए उपयोग करता है।
ध्यान दें कि कम से कम महत्वपूर्ण अंक में केवल तीन संभावित मान हो सकते हैं: "0", "3", या "7"।
इसके लिए कई समाधान / समाधान हैं जो आप उपयोग कर सकते हैं।
-- Option 1
SELECT
*
FROM A
WHERE posted_date >= '2015-07-27 00:00:00.000'
AND posted_date < '2015-07-28 00:00:00.000' --Round up and remove equality
-- Option 2
SELECT
*
FROM A
WHERE posted_date >= '2015-07-27 00:00:00.000'
AND posted_date <= '2015-07-27 23:59:59.997' --Round down and keep equality
-- Option 3
SELECT
*
FROM A
WHERE CAST(posted_date AS DATE) = '2015-07-27' -- Use different data type
-- Option 4
SELECT
*
FROM A
WHERE CONVERT(CHAR(8), DateColumn, 112) = '20150727' -- Cast to string stripping off time
-- Option 5
SELECT
*
FROM A
WHERE posted_date BETWEEN '2015-07-27 00:00:00.000'
AND '2015-07-27 23:59:59.997' --Use between
मैंने जिन पाँच विकल्पों के ऊपर प्रस्तुत किया है उनमें से मैं विकल्प 1 और 3 को ही व्यवहार्य विकल्प मानूंगा। वे आपके इरादे को स्पष्ट रूप से व्यक्त करते हैं, और यदि आप डेटा प्रकारों को अपडेट करते हैं तो वे टूटने वाले नहीं हैं। यदि आप SQL Server 2008 या नए का उपयोग कर रहे हैं तो मुझे लगता है कि विकल्प 3 आपका पसंदीदा तरीका होना चाहिए। यही कारण है कि विशेष रूप से सच है अगर आप का उपयोग करने से दूर बदल सकते हैं DATETIMEएक करने के लिए डेटाप्रकार DATEअपने लिए डेटा प्रकार posted_date
स्तंभ।
विकल्प 3 के बारे में, कुछ मुद्दों के बारे में बहुत अच्छी व्याख्या यहां पाई जा सकती है: कास्ट डेट टू सर्जेबल है लेकिन क्या यह एक अच्छा विचार है?
मुझे विकल्प 2 और 5 पसंद नहीं है क्योंकि .997
भिन्नात्मक सेकंड केवल एक और जादुई संख्या होने जा रही है जिसे लोग "ठीक" करना चाहते हैं। कुछ और कारणों BETWEEN
से आप इस पोस्ट को चेकआउट नहीं करना चाहते हैं ।
मुझे विकल्प 4 पसंद नहीं है क्योंकि तुलनात्मक उद्देश्यों के लिए डेटा प्रकारों को एक स्ट्रिंग में परिवर्तित करना मुझे गंदा लगता है। SQL सर्वर में इससे बचने का एक और गुणात्मक कारण यह है कि यह sargability उर्फ को प्रभावित करता है जिसे आप अनुक्रमणिका की तलाश नहीं कर सकते हैं और जिसके परिणामस्वरूप अक्सर खराब प्रदर्शन होगा।
डेट रेंज प्रश्नों को संभालने के सही तरीके और गलत तरीके के बारे में अधिक जानकारी के लिए आरोन बर्ट्रेंड द्वारा इस पोस्ट की जांच करें ।
अलग में आप और आपकी मूल क्वेरी रखने के लिए सक्षम हो जाएगा इसलिए अगर आप अपने अपने को बदलने वांछित के रूप में व्यवहार होता posted_date
एक से स्तंभ DATETIMEएक करने के लिए DATETIME2(3)
। यह सर्वर पर स्टोरेज स्पेस को बचाएगा, आपको एक ही परिशुद्धता पर अधिक सटीकता देगा, अधिक मानकों का अनुपालन / पोर्टेबल हो सकता है, और यदि भविष्य में आपकी ज़रूरतें बदलती हैं तो आप सटीकता / सटीकता को आसानी से समायोजित कर सकते हैं। हालाँकि, यह केवल एक विकल्प है यदि आप SQL Server 2008 या नए का उपयोग कर रहे हैं।
इस स्टैकऑवरफ्लो उत्तर के प्रति UNIX से पकड़ के 1/300
साथ एक दूसरी सटीकता के एक सामान्य ज्ञान के रूप में । साइबेस के पास एक साझा विरासत है जो उनके और डेटा प्रकारों में एक दूसरी सटीकता के समान है लेकिन उनके कम से कम महत्वपूर्ण अंक "0", "3" और "6" पर एक स्पर्श भिन्न हैं। मेरी राय में एक दूसरे और / या 3.33ms सटीकता का एक दुर्भाग्यपूर्ण वास्तुशिल्प निर्णय है क्योंकि SQL सर्वर के डेटा प्रकार में 4 बाइट ब्लॉक आसानी से 1ms सटीकता का समर्थन कर सकता है।DATETIME1/300
DATETIME
TIME
1/300
DATETIME
datetime3
परिशुद्धता के 70 (बनाम 7) अंकों के साथ? सबसे अच्छा अभ्यास एक ऐसे मूल्य का उपयोग करना है जहां परिशुद्धता मायने नहीं रखती है, <<अगले दूसरे की शुरुआत, मिनट, घंटे या दिन बनाम <= पहले दूसरे, मिनट, घंटे या दिन का अंत।
अव्यवस्थित रूपांतरण
मेरा मानना है कि पोस्ट किया गया_डेट डेटा प्रकार डेटाटाइम है। हालांकि इससे कोई फर्क नहीं पड़ता कि दूसरी तरफ का टाइप डेटाइम, डेटाटाइम 2 या सिर्फ टाइम है क्योंकि स्ट्रिंग (वर्चर) को कथित तौर पर डेटाटाइम में बदल दिया जाएगा।
Post_date को एक डाइमटाइम 2 (या समय) के रूप में घोषित करने के साथ, posted_date <= '2015-07-27 23:59:59.99999'
जहां क्लॉज विफल हो जाता है क्योंकि 23:59:59.99999
पूरी तरह से वैध डेटटाइम 2 मान है, यह मान्य डेटटाइम मान नहीं है:
Conversion failed when converting date and/or time from character string.
टाइमटाइम के लिए समय सीमा
डेटाइम की समय सीमा 23: 59: 59.997 के माध्यम से 00:00:00 है। इसलिए 23: 59: 59.999 सीमा से बाहर है और इसे निकटतम मूल्य के लिए ऊपर या नीचे गोल करना पड़ता है।
शुद्धता
इसके अलावा .टाइम मूल्यों को .000, .003, या .007 सेकंड की वेतन वृद्धि द्वारा राउंड किया जाता है। (अर्थात। 000, 003, 007, 010, 013, 017, 020, ..., 997)
यह मान के साथ ऐसा नहीं है 2015-07-27 23:59:59.999
जो इस सीमा के भीतर है: 2015-07-27 23:59:59.997
और 2015-07-28 0:00:00.000
।
यह सीमा निकटतम पूर्ववर्ती और निम्नलिखित विकल्पों के अनुरूप है, दोनों को .000, .003 या .007 के साथ समाप्त होता है।
ऊपर या नीचे गोलाई ?
क्योंकि यह 2015-07-28 0:00:00.000
(+1 बनाम -2) की तुलना में करीब है 2015-07-27 23:59:59.997
, स्ट्रिंग को गोल किया गया है और यह डेटाटाइम मान बन गया है 2015-07-28 0:00:00.000
:।
एक ऊपरी सीमा जैसे 2015-07-27 23:59:59.998
(या .995, .996, .997, .998) के साथ, यह राउंड डाउन हो जाता था 2015-07-27 23:59:59.997
और आप क्वेरी उम्मीद के मुताबिक काम करते थे। हालांकि यह एक समाधान नहीं है, लेकिन सिर्फ एक भाग्यशाली मूल्य होगा।
डेटाटाइम 2 या समय प्रकार
डेटाटाइम 2 और समय समय सीमाएं 100ns की सटीकता (अंतिम अंक जब 7 अंकों की सटीकता के साथ उपयोग की जाती हैं) के 00:00:00.0000000
माध्यम से होती हैं 23:59:59.9999999
।
हालाँकि एक डेटटाइम (3) रेंज डेटाइम रेंज के समान नहीं है:
0:0:00.000
करने के लिए23:59:59.997
0:0:00.000000000
से23:59:59.999
समाधान
अंत में, यह अगले दिन से नीचे की तारीखों की तुलना में नीचे की तारीखों को देखने के लिए सुरक्षित है या आप इसे दिन के समय का अंतिम टुकड़ा मानते हैं। यह मुख्य रूप से है क्योंकि आप जानते हैं कि अगले दिन हमेशा 0: 00: 00.000 से शुरू होता है, लेकिन विभिन्न डेटा प्रकारों का दिन के अंत में एक ही समय नहीं हो सकता है:
Datetime `0:0:00.000` to `23:59:59.997`
Datetime2 `0:0:00.000000000` to `23:59:59.999-999-900`
Time2 `0:0:00.000000000` to `23:59:59.999-999-900`
< 2015-07-28 0:00:00.000
आपको एक सटीक परिणाम देगा और सबसे अच्छा विकल्प है<= 2015-07-27 23:59:59.xxx
जब आप सोचते हैं कि यह होना चाहिए तो यह गोल नहीं होने पर अप्रत्याशित मान लौटा सकता है।हम सोच सकते हैं कि [पोस्ट_डेट] को बदलकर डाटटाइम 2 और इसकी उच्च परिशुद्धता इस समस्या को ठीक कर सकती है लेकिन यह मदद नहीं करेगा क्योंकि स्ट्रिंग अभी भी डाटटाइम में परिवर्तित है। हालाँकि, यदि कोई कलाकार जोड़ा जाता है cast(2015-07-27 23:59:59.999' as datetime2)
, तो यह ठीक काम करता है
कास्ट और कन्वर्ट
कास्ट एक मान को 3 अंकों तक डेटाटाइम में या 9 अंकों के साथ डेटाटाइम 2 या समय में बदल सकता है और इसे सही सटीकता के लिए राउंड कर सकता है।
यह ध्यान दिया जाना चाहिए कि डेटाटाइम 2 और टाइम 2 के कास्ट अलग परिणाम दे सकते हैं:
select cast('20150101 23:59:59.999999999' as datetime2(7))
2015-05-03 00: 00: 00.0000000 (999999949 से अधिक मूल्य के लिए) का राउंड अप हैselect cast('23:59:59.999999999' as time(7))
=> 23: 59: 59.9999999यह 0, 3 और 7 वेतन वृद्धि के साथ होने वाली समस्या को ठीक करने का एक प्रकार है, हालांकि अगले दिन के 1 नैनो सेकंड (हमेशा 0: 00: 00.000) से पहले तारीखों की तलाश करना हमेशा बेहतर होता है।
स्रोत MSDN: डेटाइम (Transact-SQL)
यह गोलाई है
select cast('2015-07-27 23:59:59.999' as datetime)
returns 2015-07-28 00:00:00.000
.998, .997, .996, .995 सभी डाली / .997 को राउंड
उपयोग करना चाहिए
select *
from A
where posted_date >= '2015-07-27 00:00:00.000'
and posted_date < '2015-07-28 00:00:00.000'
या
where cast(posted_date as date) = '2015-07-27'
इस लिंक में सटीकता
हमेशा देखें .000, .003, .007 के रूप में रिपोर्ट किया गया
select * from A where date(posted_date) = '2015-07-27'
'DATE' is not a recognized built-in function name.
gives you control of DATE and TIME as opposed to datetime.
इसका क्या मतलब है?