views:

104

answers:

4

I have datecreated field in a table. It contains value as "2009-12-30 11:47:20:297" I have a query like this:

select * 
  from table 
 where DateCreated = getdate()

Although one row exists with today's date, I am not getting that row while executing above query. Can anybody help?

+3  A: 

You can use something like this with Sql Server

CREATE FUNCTION [dbo].[udf_DateOnly](@DateTime DATETIME)
RETURNS DATETIME
AS
BEGIN
    RETURN DATEADD(dd,0, DATEDIFF(dd,0,@DateTime))
END

This line

DATEADD(dd,0, DATEDIFF(dd,0,@DateTime))

will strip out the Date portion.

astander
+1  A: 

You can convert datetime to a string with only the date by using
CONVERT(varchar(8), GETDATE(), 112)

If needed, you can then change it back to datetime and as a result you'll get a datetime with the hours, minutes, seconds and milliseconds set to zero.

Carlos
Although this works, I wouldn't recommend it. For a start, the string manipulation done internally reduces performance. But more importantly it leads developers to some bad and potentially dangerous habits.
Craig Young
Definitely good to know. Can you also tell me what are the potential dangers involved in using this approach?
Carlos
+3  A: 

The reason why your query doesn't return the row you expect, is because GETDATE() returns the date and time portion at the moment the query was executed. The value in your DateCreated column will not match the time portion, so no rows are returned.

There are various ways to construct a query so that it evaluates the date based on only the date component. Here's one example:

WHERE YEAR(datecreated) = YEAR(GETDATE())
  AND MONTH(datecreated) = MONTH(GETDATE())
  AND DAY(datecreated) = DAY(GETDATE())

The unfortunate reality is that any query using a function on the column means that if an index exists on the column, it can't be used.

OMG Ponies
but you could make the YEAR(), MONTH(), DAY() into persisted computed columns on your table, and then index those.....
marc_s
@marc_s: That sounds like something someone who abuses artificial keys would come up with. (Sorry, I couldn't resist ;) )... Seriously though, look at Peter Di Cecco's answer - it is the best one, providing opportunity to use indexes.
Craig Young
@Craig: well, depends - if you need to e.g. select on just the month a lot of times (for monthly reports etc.), this might be a valid approach
marc_s
@marc_s: No. If you are doing a monthly report, you select the daterange from the beginning of the month to the end of the month. If you are doing a report for a specific month across all your years, then 1 twelfth of your data will typically not be considered selective enough to use an index unless it's clustered. So again normal dates are better... That said, I do agree: **if** the requirements do **genuinely** indicate that breaking a date up into its constituents would be beneficial, then by all means - go ahead. (Just bear in mind the negative impacts of such a decision.)
Craig Young
+2  A: 

The datetime field includes both the date and the time, accurate to the millisecond. Your query will only work if it is the exact millisecond stored in the database.

To check if it is today, but ignore the time of day, you can check for a range like this:

select * from table where
DateCreated >= '2009-12-30' and
DateCreated < '2009-12-31'

You can use that in conjunction with a function that converts the current date, as astander or Khilon has posted. Here is a full example using astander's answer. Also, as Craig Young points out, this will work with indexes.

select * from table where
DateCreated >= DATEDIFF(dd,0,GETDATE()) and
DateCreated < DATEDIFF(dd,0,GETDATE())
Peter Di Cecco
+1: Just to emphasise, the range must be inclusive on one side and exclusive on the other. I.e. >= and < exactly as shown. BTW, to be pedantic, datetime is only _accurate_ to about 17 milliseconds.
Craig Young
PS: I prefer astander's mechanism to remove time from the `GETDATE()` result. I.e. `where DateCreated >= DATEDIFF(dd,0,GETDATE()) and DateCreated < DATEDIFF(dd,0,GETDATE())`
Craig Young