Incorrect date comparison results in SQL Server 2008 R2
up vote
0
down vote
favorite
I have a LINQ 2 SQL query that's getting me a list of results for the month of February 2012. The resulting where clause is
DECLARE @p0 DateTime = '2012-02-01 00:00:00.000'
DECLARE @p1 DateTime = '2012-02-29 23:59:59.999'
....
WHERE (CONVERT(DATE, [t0].[DatePlaced]) >= @p0) AND (CONVERT(DATE, [t0].[DatePlaced]) <= @p1)
When this runs I'm getting results for 3/1/2012 showing up as well as all the results for 2/2012.
If I change the where clause to use BETWEEN
then the results only contain dates for February.
WHERE [t0].[DatePlaced] BETWEEN @p0 AND @p1
I'm using .net 4 and SQL Server 2008 R2 with and without SP1.
Switching the dates to 3/1/2011 and my query's end date to '2011-02-28 23:59:59.999'
yielded the same results.
Is there another way to get the results for just 2/2012 aside from using BETWEEN which LINQ 2 SQL doesn't support?
linq-to-sql datetime sql-server-2008-r2
add a comment |
up vote
0
down vote
favorite
I have a LINQ 2 SQL query that's getting me a list of results for the month of February 2012. The resulting where clause is
DECLARE @p0 DateTime = '2012-02-01 00:00:00.000'
DECLARE @p1 DateTime = '2012-02-29 23:59:59.999'
....
WHERE (CONVERT(DATE, [t0].[DatePlaced]) >= @p0) AND (CONVERT(DATE, [t0].[DatePlaced]) <= @p1)
When this runs I'm getting results for 3/1/2012 showing up as well as all the results for 2/2012.
If I change the where clause to use BETWEEN
then the results only contain dates for February.
WHERE [t0].[DatePlaced] BETWEEN @p0 AND @p1
I'm using .net 4 and SQL Server 2008 R2 with and without SP1.
Switching the dates to 3/1/2011 and my query's end date to '2011-02-28 23:59:59.999'
yielded the same results.
Is there another way to get the results for just 2/2012 aside from using BETWEEN which LINQ 2 SQL doesn't support?
linq-to-sql datetime sql-server-2008-r2
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I have a LINQ 2 SQL query that's getting me a list of results for the month of February 2012. The resulting where clause is
DECLARE @p0 DateTime = '2012-02-01 00:00:00.000'
DECLARE @p1 DateTime = '2012-02-29 23:59:59.999'
....
WHERE (CONVERT(DATE, [t0].[DatePlaced]) >= @p0) AND (CONVERT(DATE, [t0].[DatePlaced]) <= @p1)
When this runs I'm getting results for 3/1/2012 showing up as well as all the results for 2/2012.
If I change the where clause to use BETWEEN
then the results only contain dates for February.
WHERE [t0].[DatePlaced] BETWEEN @p0 AND @p1
I'm using .net 4 and SQL Server 2008 R2 with and without SP1.
Switching the dates to 3/1/2011 and my query's end date to '2011-02-28 23:59:59.999'
yielded the same results.
Is there another way to get the results for just 2/2012 aside from using BETWEEN which LINQ 2 SQL doesn't support?
linq-to-sql datetime sql-server-2008-r2
I have a LINQ 2 SQL query that's getting me a list of results for the month of February 2012. The resulting where clause is
DECLARE @p0 DateTime = '2012-02-01 00:00:00.000'
DECLARE @p1 DateTime = '2012-02-29 23:59:59.999'
....
WHERE (CONVERT(DATE, [t0].[DatePlaced]) >= @p0) AND (CONVERT(DATE, [t0].[DatePlaced]) <= @p1)
When this runs I'm getting results for 3/1/2012 showing up as well as all the results for 2/2012.
If I change the where clause to use BETWEEN
then the results only contain dates for February.
WHERE [t0].[DatePlaced] BETWEEN @p0 AND @p1
I'm using .net 4 and SQL Server 2008 R2 with and without SP1.
Switching the dates to 3/1/2011 and my query's end date to '2011-02-28 23:59:59.999'
yielded the same results.
Is there another way to get the results for just 2/2012 aside from using BETWEEN which LINQ 2 SQL doesn't support?
linq-to-sql datetime sql-server-2008-r2
linq-to-sql datetime sql-server-2008-r2
asked Mar 1 '12 at 21:06
Brian Surowiec
9,88063463
9,88063463
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
up vote
4
down vote
accepted
.999 rounds up to midnight of the next day. You can check this:
DECLARE @p1 DateTime = '2012-02-29 23:59:59.999';
SELECT @p1;
What do you get?
Instead of trying to figure out the last instant of today (which will be different depending on the data type and precision), what you want instead is an open-ended date range:
DECLARE @p0 DATE = '2012-02-01',
@p1 DATE = '2012-03-01';
....
WHERE [t0].[DatePlaced] >= @p0
AND [t0].[DatePlaced] < @p1
Even easier would be to just pass in the starting date and say:
DECLARE @p0 DATE = '2012-02-01';
....
WHERE [t0].DatePlaced >= @p0
AND [t0].DatePlaced < DATEADD(MONTH, 1, @p0)
For some elaborate ideas about datetime best practices:
- Bad habits to kick : mis-handling date / range queries
For some info on why BETWEEN
(and by extension >= AND <=
) is evil:
- What do BETWEEN and the devil have in common?
add a comment |
up vote
3
down vote
If you need to select by month often, you could consider adding two computed columns to your table - one for the month, one for the year:
ALTER TABLE dbo.YourTable
ADD DatePlacedYear AS YEAR(DatePlaced) PERSISTED
ALTER TABLE dbo.YourTable
ADD DatePlacedMonth AS MONTH(DatePlaced) PERSISTED
Those two new columns are automatically computed by SQL Server, they're persisted (e.g. part of the table's storage), and you can even put an index on them, if that makes sense for you.
With those in place, you could now use a query like:
SELECT (columns)
FROM dbo.YourTable
WHERE DatePlacedYear = 2012 AND DatePlacedMonth = 2
to get all data from February 2012.
It's a classic space-vs-speed trade-off - by storing the two extra columns for each row, you need more space - but in return, querying gets easier and if you have an index on (DatePlacedYear, DatePlacedMonth)
, your queries should (ideally) be quite fast.
Instead of adding computed columns I simply compared against the Month and Year parts of the date. I'm sure there's a performance trade off but it's only for internal reporting so that's not much of an issue right now.
– Brian Surowiec
Mar 11 '12 at 4:47
add a comment |
up vote
0
down vote
Instead of using AddMilliseconds(-1)
try use AddMilliseconds(-3)
See this question how SQL Server treats the milliseconds
2
Relying on milliseconds is problematic. What if the underlying data type is converted to SMALLDATETIME? Now your result rounds up again. What if it is converted to DATETIME2(>2)? Now the end of your range is actually before the end of the day, and you could theoretically miss data. An open-ended date range is really the only future-proof way to get a whole day's worth of data.
– Aaron Bertrand
Mar 2 '12 at 0:14
add a comment |
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
4
down vote
accepted
.999 rounds up to midnight of the next day. You can check this:
DECLARE @p1 DateTime = '2012-02-29 23:59:59.999';
SELECT @p1;
What do you get?
Instead of trying to figure out the last instant of today (which will be different depending on the data type and precision), what you want instead is an open-ended date range:
DECLARE @p0 DATE = '2012-02-01',
@p1 DATE = '2012-03-01';
....
WHERE [t0].[DatePlaced] >= @p0
AND [t0].[DatePlaced] < @p1
Even easier would be to just pass in the starting date and say:
DECLARE @p0 DATE = '2012-02-01';
....
WHERE [t0].DatePlaced >= @p0
AND [t0].DatePlaced < DATEADD(MONTH, 1, @p0)
For some elaborate ideas about datetime best practices:
- Bad habits to kick : mis-handling date / range queries
For some info on why BETWEEN
(and by extension >= AND <=
) is evil:
- What do BETWEEN and the devil have in common?
add a comment |
up vote
4
down vote
accepted
.999 rounds up to midnight of the next day. You can check this:
DECLARE @p1 DateTime = '2012-02-29 23:59:59.999';
SELECT @p1;
What do you get?
Instead of trying to figure out the last instant of today (which will be different depending on the data type and precision), what you want instead is an open-ended date range:
DECLARE @p0 DATE = '2012-02-01',
@p1 DATE = '2012-03-01';
....
WHERE [t0].[DatePlaced] >= @p0
AND [t0].[DatePlaced] < @p1
Even easier would be to just pass in the starting date and say:
DECLARE @p0 DATE = '2012-02-01';
....
WHERE [t0].DatePlaced >= @p0
AND [t0].DatePlaced < DATEADD(MONTH, 1, @p0)
For some elaborate ideas about datetime best practices:
- Bad habits to kick : mis-handling date / range queries
For some info on why BETWEEN
(and by extension >= AND <=
) is evil:
- What do BETWEEN and the devil have in common?
add a comment |
up vote
4
down vote
accepted
up vote
4
down vote
accepted
.999 rounds up to midnight of the next day. You can check this:
DECLARE @p1 DateTime = '2012-02-29 23:59:59.999';
SELECT @p1;
What do you get?
Instead of trying to figure out the last instant of today (which will be different depending on the data type and precision), what you want instead is an open-ended date range:
DECLARE @p0 DATE = '2012-02-01',
@p1 DATE = '2012-03-01';
....
WHERE [t0].[DatePlaced] >= @p0
AND [t0].[DatePlaced] < @p1
Even easier would be to just pass in the starting date and say:
DECLARE @p0 DATE = '2012-02-01';
....
WHERE [t0].DatePlaced >= @p0
AND [t0].DatePlaced < DATEADD(MONTH, 1, @p0)
For some elaborate ideas about datetime best practices:
- Bad habits to kick : mis-handling date / range queries
For some info on why BETWEEN
(and by extension >= AND <=
) is evil:
- What do BETWEEN and the devil have in common?
.999 rounds up to midnight of the next day. You can check this:
DECLARE @p1 DateTime = '2012-02-29 23:59:59.999';
SELECT @p1;
What do you get?
Instead of trying to figure out the last instant of today (which will be different depending on the data type and precision), what you want instead is an open-ended date range:
DECLARE @p0 DATE = '2012-02-01',
@p1 DATE = '2012-03-01';
....
WHERE [t0].[DatePlaced] >= @p0
AND [t0].[DatePlaced] < @p1
Even easier would be to just pass in the starting date and say:
DECLARE @p0 DATE = '2012-02-01';
....
WHERE [t0].DatePlaced >= @p0
AND [t0].DatePlaced < DATEADD(MONTH, 1, @p0)
For some elaborate ideas about datetime best practices:
- Bad habits to kick : mis-handling date / range queries
For some info on why BETWEEN
(and by extension >= AND <=
) is evil:
- What do BETWEEN and the devil have in common?
edited Nov 10 at 16:18
answered Mar 1 '12 at 21:31
Aaron Bertrand
205k27357401
205k27357401
add a comment |
add a comment |
up vote
3
down vote
If you need to select by month often, you could consider adding two computed columns to your table - one for the month, one for the year:
ALTER TABLE dbo.YourTable
ADD DatePlacedYear AS YEAR(DatePlaced) PERSISTED
ALTER TABLE dbo.YourTable
ADD DatePlacedMonth AS MONTH(DatePlaced) PERSISTED
Those two new columns are automatically computed by SQL Server, they're persisted (e.g. part of the table's storage), and you can even put an index on them, if that makes sense for you.
With those in place, you could now use a query like:
SELECT (columns)
FROM dbo.YourTable
WHERE DatePlacedYear = 2012 AND DatePlacedMonth = 2
to get all data from February 2012.
It's a classic space-vs-speed trade-off - by storing the two extra columns for each row, you need more space - but in return, querying gets easier and if you have an index on (DatePlacedYear, DatePlacedMonth)
, your queries should (ideally) be quite fast.
Instead of adding computed columns I simply compared against the Month and Year parts of the date. I'm sure there's a performance trade off but it's only for internal reporting so that's not much of an issue right now.
– Brian Surowiec
Mar 11 '12 at 4:47
add a comment |
up vote
3
down vote
If you need to select by month often, you could consider adding two computed columns to your table - one for the month, one for the year:
ALTER TABLE dbo.YourTable
ADD DatePlacedYear AS YEAR(DatePlaced) PERSISTED
ALTER TABLE dbo.YourTable
ADD DatePlacedMonth AS MONTH(DatePlaced) PERSISTED
Those two new columns are automatically computed by SQL Server, they're persisted (e.g. part of the table's storage), and you can even put an index on them, if that makes sense for you.
With those in place, you could now use a query like:
SELECT (columns)
FROM dbo.YourTable
WHERE DatePlacedYear = 2012 AND DatePlacedMonth = 2
to get all data from February 2012.
It's a classic space-vs-speed trade-off - by storing the two extra columns for each row, you need more space - but in return, querying gets easier and if you have an index on (DatePlacedYear, DatePlacedMonth)
, your queries should (ideally) be quite fast.
Instead of adding computed columns I simply compared against the Month and Year parts of the date. I'm sure there's a performance trade off but it's only for internal reporting so that's not much of an issue right now.
– Brian Surowiec
Mar 11 '12 at 4:47
add a comment |
up vote
3
down vote
up vote
3
down vote
If you need to select by month often, you could consider adding two computed columns to your table - one for the month, one for the year:
ALTER TABLE dbo.YourTable
ADD DatePlacedYear AS YEAR(DatePlaced) PERSISTED
ALTER TABLE dbo.YourTable
ADD DatePlacedMonth AS MONTH(DatePlaced) PERSISTED
Those two new columns are automatically computed by SQL Server, they're persisted (e.g. part of the table's storage), and you can even put an index on them, if that makes sense for you.
With those in place, you could now use a query like:
SELECT (columns)
FROM dbo.YourTable
WHERE DatePlacedYear = 2012 AND DatePlacedMonth = 2
to get all data from February 2012.
It's a classic space-vs-speed trade-off - by storing the two extra columns for each row, you need more space - but in return, querying gets easier and if you have an index on (DatePlacedYear, DatePlacedMonth)
, your queries should (ideally) be quite fast.
If you need to select by month often, you could consider adding two computed columns to your table - one for the month, one for the year:
ALTER TABLE dbo.YourTable
ADD DatePlacedYear AS YEAR(DatePlaced) PERSISTED
ALTER TABLE dbo.YourTable
ADD DatePlacedMonth AS MONTH(DatePlaced) PERSISTED
Those two new columns are automatically computed by SQL Server, they're persisted (e.g. part of the table's storage), and you can even put an index on them, if that makes sense for you.
With those in place, you could now use a query like:
SELECT (columns)
FROM dbo.YourTable
WHERE DatePlacedYear = 2012 AND DatePlacedMonth = 2
to get all data from February 2012.
It's a classic space-vs-speed trade-off - by storing the two extra columns for each row, you need more space - but in return, querying gets easier and if you have an index on (DatePlacedYear, DatePlacedMonth)
, your queries should (ideally) be quite fast.
answered Mar 1 '12 at 21:25
marc_s
564k12510891242
564k12510891242
Instead of adding computed columns I simply compared against the Month and Year parts of the date. I'm sure there's a performance trade off but it's only for internal reporting so that's not much of an issue right now.
– Brian Surowiec
Mar 11 '12 at 4:47
add a comment |
Instead of adding computed columns I simply compared against the Month and Year parts of the date. I'm sure there's a performance trade off but it's only for internal reporting so that's not much of an issue right now.
– Brian Surowiec
Mar 11 '12 at 4:47
Instead of adding computed columns I simply compared against the Month and Year parts of the date. I'm sure there's a performance trade off but it's only for internal reporting so that's not much of an issue right now.
– Brian Surowiec
Mar 11 '12 at 4:47
Instead of adding computed columns I simply compared against the Month and Year parts of the date. I'm sure there's a performance trade off but it's only for internal reporting so that's not much of an issue right now.
– Brian Surowiec
Mar 11 '12 at 4:47
add a comment |
up vote
0
down vote
Instead of using AddMilliseconds(-1)
try use AddMilliseconds(-3)
See this question how SQL Server treats the milliseconds
2
Relying on milliseconds is problematic. What if the underlying data type is converted to SMALLDATETIME? Now your result rounds up again. What if it is converted to DATETIME2(>2)? Now the end of your range is actually before the end of the day, and you could theoretically miss data. An open-ended date range is really the only future-proof way to get a whole day's worth of data.
– Aaron Bertrand
Mar 2 '12 at 0:14
add a comment |
up vote
0
down vote
Instead of using AddMilliseconds(-1)
try use AddMilliseconds(-3)
See this question how SQL Server treats the milliseconds
2
Relying on milliseconds is problematic. What if the underlying data type is converted to SMALLDATETIME? Now your result rounds up again. What if it is converted to DATETIME2(>2)? Now the end of your range is actually before the end of the day, and you could theoretically miss data. An open-ended date range is really the only future-proof way to get a whole day's worth of data.
– Aaron Bertrand
Mar 2 '12 at 0:14
add a comment |
up vote
0
down vote
up vote
0
down vote
Instead of using AddMilliseconds(-1)
try use AddMilliseconds(-3)
See this question how SQL Server treats the milliseconds
Instead of using AddMilliseconds(-1)
try use AddMilliseconds(-3)
See this question how SQL Server treats the milliseconds
edited May 23 '17 at 10:34
Community♦
11
11
answered Mar 1 '12 at 21:34
Adrian Iftode
13.3k23465
13.3k23465
2
Relying on milliseconds is problematic. What if the underlying data type is converted to SMALLDATETIME? Now your result rounds up again. What if it is converted to DATETIME2(>2)? Now the end of your range is actually before the end of the day, and you could theoretically miss data. An open-ended date range is really the only future-proof way to get a whole day's worth of data.
– Aaron Bertrand
Mar 2 '12 at 0:14
add a comment |
2
Relying on milliseconds is problematic. What if the underlying data type is converted to SMALLDATETIME? Now your result rounds up again. What if it is converted to DATETIME2(>2)? Now the end of your range is actually before the end of the day, and you could theoretically miss data. An open-ended date range is really the only future-proof way to get a whole day's worth of data.
– Aaron Bertrand
Mar 2 '12 at 0:14
2
2
Relying on milliseconds is problematic. What if the underlying data type is converted to SMALLDATETIME? Now your result rounds up again. What if it is converted to DATETIME2(>2)? Now the end of your range is actually before the end of the day, and you could theoretically miss data. An open-ended date range is really the only future-proof way to get a whole day's worth of data.
– Aaron Bertrand
Mar 2 '12 at 0:14
Relying on milliseconds is problematic. What if the underlying data type is converted to SMALLDATETIME? Now your result rounds up again. What if it is converted to DATETIME2(>2)? Now the end of your range is actually before the end of the day, and you could theoretically miss data. An open-ended date range is really the only future-proof way to get a whole day's worth of data.
– Aaron Bertrand
Mar 2 '12 at 0:14
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f9524086%2fincorrect-date-comparison-results-in-sql-server-2008-r2%23new-answer', 'question_page');
}
);
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password