Click here to monitor SSC
SQLServerCentral is supported by Red Gate Software Ltd.
 
Log in  ::  Register  ::  Not logged in
 
 
 
        
Home       Members    Calendar    Who's On


Add to briefcase 123»»»

Date Comparisons Expand / Collapse
Author
Message
Posted Monday, January 07, 2013 10:12 AM
SSC Rookie

SSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC Rookie

Group: General Forum Members
Last Login: Thursday, May 09, 2013 8:21 AM
Points: 35, Visits: 57
Other than issues with sorting and MAX, are there any potential issues with using something like CONVERT([varchar](10), datetimefield, 101) which yields a mm/dd/yyyy varchar value.

That is, the WHERE > and < statement will still work properly as long as it is being compared to a true datetime value?


Post #1403732
Posted Monday, January 07, 2013 10:15 AM


SSCoach

SSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoach

Group: General Forum Members
Last Login: Tuesday, May 21, 2013 1:55 PM
Points: 15,442, Visits: 9,571
If you mean something like:

WHERE MyDateTimeColumn >= CONVERT(VARCHAR(25), MyOtherDateTimeColumn, 101)
AND MyDateTimeColumn < CONVERT(VARCHAR(25), YetAnotherDateTimeColumn, 101)

Then, yes, that will work. It'll be inefficient, but it will work.


- Gus "GSquared", RSVP, OODA, MAP, NMVP, FAQ, SAT, SQL, DNA, RNA, UOI, IOU, AM, PM, AD, BC, BCE, USA, UN, CF, ROFL, LOL, ETC
Property of The Thread

"Nobody knows the age of the human race, but everyone agrees it's old enough to know better." - Anon
Post #1403734
Posted Monday, January 07, 2013 10:22 AM
SSC Rookie

SSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC Rookie

Group: General Forum Members
Last Login: Thursday, May 09, 2013 8:21 AM
Points: 35, Visits: 57
The actual syntax would be :

DECLARE @StartDate as date
SET @StartDate = some calculated date

DECLARE @EndDate as date
SET @EndDate = another calculated date


CONVERT([varchar](10), MyDatetimeColumn, 101) AS MyDate
...
WHERE MyDate >= @StartDate and MyDate <= @EndDate


I am not so concerned about efficiency as I am accuracy at this time.
Post #1403738
Posted Monday, January 07, 2013 12:35 PM
Ten Centuries

Ten CenturiesTen CenturiesTen CenturiesTen CenturiesTen CenturiesTen CenturiesTen CenturiesTen Centuries

Group: General Forum Members
Last Login: Wednesday, May 22, 2013 3:56 PM
Points: 1,324, Visits: 1,778
paul.j.kemna (1/7/2013)
The actual syntax would be :

DECLARE @StartDate as date
SET @StartDate = some calculated date

DECLARE @EndDate as date
SET @EndDate = another calculated date


CONVERT([varchar](10), MyDatetimeColumn, 101) AS MyDate
...
WHERE MyDate >= @StartDate and MyDate <= @EndDate


I am not so concerned about efficiency as I am accuracy at this time.



You should use "<" rather than "<=" on the @EndDate comparison:

WHERE MyDate >= @StartDate and MyDate < @EndDate


Adjust @EndDate accordingly before the SQL statement. For example, if you're working with days, set @EndDate to the next day at midnight. If you're working with minutes, set @EndDate to the next minute.

That makes sure the comparisons remain accurate for all different date/datetime data types.


SQL DBA,SQL Server MVP('07, '08, '09)
One man with courage makes a majority. Andrew Jackson
Post #1403818
Posted Monday, January 07, 2013 12:49 PM


SSCoach

SSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoach

Group: General Forum Members
Last Login: Tuesday, May 21, 2013 1:55 PM
Points: 15,442, Visits: 9,571
paul.j.kemna (1/7/2013)
The actual syntax would be :

DECLARE @StartDate as date
SET @StartDate = some calculated date

DECLARE @EndDate as date
SET @EndDate = another calculated date


CONVERT([varchar](10), MyDatetimeColumn, 101) AS MyDate
...
WHERE MyDate >= @StartDate and MyDate <= @EndDate


I am not so concerned about efficiency as I am accuracy at this time.


Why use the Convert() function on the column in the Where clause? (For that matter, why use it in the Select clause? Date formatting should be done in the presentation layer, not the DAL. But that's beyond the scope of the original question.)

Or is that not what you meant here? You're not converting in your Where clause, and I'm misreading something?


- Gus "GSquared", RSVP, OODA, MAP, NMVP, FAQ, SAT, SQL, DNA, RNA, UOI, IOU, AM, PM, AD, BC, BCE, USA, UN, CF, ROFL, LOL, ETC
Property of The Thread

"Nobody knows the age of the human race, but everyone agrees it's old enough to know better." - Anon
Post #1403826
Posted Monday, January 07, 2013 1:07 PM
SSC Rookie

SSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC Rookie

Group: General Forum Members
Last Login: Thursday, May 09, 2013 8:21 AM
Points: 35, Visits: 57
No, I know what I SHOULD do. I am looking at previous processes and just need to know if this query would return the correct results. All of my testing indicates that it would, but I just want to hear it from someone else.
Post #1403840
Posted Monday, January 07, 2013 1:25 PM


SSCoach

SSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoach

Group: General Forum Members
Last Login: Tuesday, May 21, 2013 1:55 PM
Points: 15,442, Visits: 9,571
Assuming "correct results" means dates between the two variable values, including the end-date value, then yes.

As mentioned, using <= @EndDate can give odd results.

For example:

DECLARE @T TABLE
(ID INT IDENTITY
PRIMARY KEY,
DT DATETIME);

INSERT INTO @T
(DT)
VALUES ('2013-01-01 06:00'),
('2013-01-02 08:00'),
('2013-01-03 23:00');

DECLARE @StartDate DATE = '2013-01-02',
@EndDate DATE = '2013-01-03';

SELECT *
FROM @T
WHERE CONVERT(CHAR(10), DT, 101) >= @StartDate
AND CONVERT(CHAR(10), DT, 101) <= @EndDate;

If "End Date" means "everything up to but not including", then this will give incorrect results. If it means everything up to and including, then it will give correct results.

So whether that will be correct or not depends on your definition of End Date.

If, for example, you want all of January 2013 in a query, then you have to assign Start Date as 1 Jan 13, and End Date as 31 Jan 13. It's a lot easier to calculate the first day of the next month, and use < instead of <=, because that skips the complexity of dealing with variable end dates (31 for Jan, 28 for Feb except when it's 29, 31 for March, 30 for April, etc.).

That's why most prefer to use >= Start Date, and < End Date, and define End Date as the "up to but not including". Then for January, you figure out the 1st of the month (dead easy), and you use DateAdd to add one month to it (again, dead easy), and you're done. No worrying about short/long/messed-up months that we inherited from Romans who couldn't figure out how to make December always be in the winter or just plain didn't care about that.

So I can't tell if it's correct or not, because I don't know how End Date is defined in your system.

Beyond that, yeah, it'll work correctly if End Date is defined as "up to and including".


- Gus "GSquared", RSVP, OODA, MAP, NMVP, FAQ, SAT, SQL, DNA, RNA, UOI, IOU, AM, PM, AD, BC, BCE, USA, UN, CF, ROFL, LOL, ETC
Property of The Thread

"Nobody knows the age of the human race, but everyone agrees it's old enough to know better." - Anon
Post #1403848
Posted Monday, January 07, 2013 1:31 PM
SSC Rookie

SSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC Rookie

Group: General Forum Members
Last Login: Thursday, May 09, 2013 8:21 AM
Points: 35, Visits: 57
Wow, that makes a lot of sense. Such a simple concept that i may have overlooked in some places.

But in this case, we are assuming that I DO want to include EndDate. My concern was the comparison of a varchar date with an "actual" datetime data type.
Post #1403853
Posted Monday, January 07, 2013 1:34 PM
Valued Member

Valued MemberValued MemberValued MemberValued MemberValued MemberValued MemberValued MemberValued Member

Group: General Forum Members
Last Login: Yesterday @ 10:29 PM
Points: 69, Visits: 318
Apropos of nothing, my favorite is


declare @i int
select @i=CONVERT(int,cast('01/07/2013' as datetime) )
SELECT * FROM table where
CAST(field AS int) = @i

It's very fast.
Post #1403854
Posted Monday, January 07, 2013 1:37 PM
Ten Centuries

Ten CenturiesTen CenturiesTen CenturiesTen CenturiesTen CenturiesTen CenturiesTen CenturiesTen Centuries

Group: General Forum Members
Last Login: Wednesday, May 22, 2013 3:56 PM
Points: 1,324, Visits: 1,778
GSquared (1/7/2013)
Assuming "correct results" means dates between the two variable values, including the end-date value, then yes.

As mentioned, using <= @EndDate can give odd results.

For example:

DECLARE @T TABLE
(ID INT IDENTITY
PRIMARY KEY,
DT DATETIME);

INSERT INTO @T
(DT)
VALUES ('2013-01-01 06:00'),
('2013-01-02 08:00'),
('2013-01-03 23:00');

DECLARE @StartDate DATE = '2013-01-02',
@EndDate DATE = '2013-01-03';

SELECT *
FROM @T
WHERE CONVERT(CHAR(10), DT, 101) >= @StartDate
AND CONVERT(CHAR(10), DT, 101) <= @EndDate;

If "End Date" means "everything up to but not including", then this will give incorrect results. If it means everything up to and including, then it will give correct results.

So whether that will be correct or not depends on your definition of End Date.

If, for example, you want all of January 2013 in a query, then you have to assign Start Date as 1 Jan 13, and End Date as 31 Jan 13. It's a lot easier to calculate the first day of the next month, and use < instead of <=, because that skips the complexity of dealing with variable end dates (31 for Jan, 28 for Feb except when it's 29, 31 for March, 30 for April, etc.).

That's why most prefer to use >= Start Date, and < End Date, and define End Date as the "up to but not including". Then for January, you figure out the 1st of the month (dead easy), and you use DateAdd to add one month to it (again, dead easy), and you're done. No worrying about short/long/messed-up months that we inherited from Romans who couldn't figure out how to make December always be in the winter or just plain didn't care about that.

So I can't tell if it's correct or not, because I don't know how End Date is defined in your system.

Beyond that, yeah, it'll work correctly if End Date is defined as "up to and including".



Yes, the month-end day issues are a strong consideration.

But from my standpoint, time is the more critical component than even the day when using <=.

Most people by default use <=, say for monthly totals, like so:

WHERE datetime_column >= '20120101' AND date_column <= '20120131'
WHERE datetime_column >= '20120201' AND date_column <= '20120229'

Look OK? No! What about rows with datetimes of '20120131 04:23' and '20120131 17:22', etc.? They are not included!

Ah, but you've thought of that, and you'll get around it like so, for your current "datetime" column:

WHERE datetime_column >= '20120101' AND datetime_column <= '20120131 23:59:59.997'

Ooh, problematic already -- note that you have to precisely specify the time -- .998 or .999 will round up to the next day.

But let's say you get past that. Then along comes SQL 2008 and "datetime2". Suddenly they need more accurate times for orders, so "datetime_column" gets changed to "datetime2".

The query is now wrong again! The "<=" time needs to be '20120131 23:59:59.9999999' (IIRC). So rows with times from "20120131 23:59:59.9971" thru .9999999 are simply ignored until/unless the query is changed.

Then, after a month, what if they decide to go back to "datetime"? Argghh!

Smalldatetime has similar issues, of course.

But note that "<" the next range value handles all of this correctly.

You stated you most wanted accuracy -- I agree 100%. And that's why I stated you should switch to the "<" method .


Edit: .998 on datetime rounds down, not up; .999 does round up to the next day.


SQL DBA,SQL Server MVP('07, '08, '09)
One man with courage makes a majority. Andrew Jackson
Post #1403855
« Prev Topic | Next Topic »

Add to briefcase 123»»»

Permissions Expand / Collapse