How to determine closest date - c#

I am a little confused about how or what the best way to determine what the closest date is to DateTime.Now is.
In my table, everything needs to be timestamped. And on a page, I need to be able to retrieve everything from the table only if the date is the closest date to now.
How would I go about this?
I am using DateTime.Now when inserting dates into the Database, and the format is like:
5/07/2011 5:28:57 PM

Here's my suggestion:
declare #DateTimeNow datetime = getdate()
select TOP (1)
RecordId
,MyDateColumn
,abs(datediff(s, MyDateColumn, #DateTimeNow)) as Diff
from
MyTable
order by
abs(datediff(s, MyDateColumn, #DateTimeNow)) asc
Do not forget to use ABS()!

How about
SELECT TOP 1 *
FROM MyTable
ORDER BY TimestampColumn DESC
Consider storing time in UTC - DateTime.UtcNow

In T-SQL you could use DateDiff:
DATEDIFF ( datepart , startdate , enddate )
http://msdn.microsoft.com/en-us/library/ms189794.aspx
or in C# you could use TimeSpan:
http://msdn.microsoft.com/en-us/library/system.timespan.aspx#Y3719

Do you only have past dates, meaning, will you ever have a date that is newer than DateTime.Now? If not, you could get by with a simple Order By on the date column selecting the newest date. Otherwise, you'll need to get a date difference between your DateTime.Now, and order by that result. e.g.
SELECT TOP 1
columnDate
FROM table1
ORDER BY DATEDIFF (ss,#passedInDate,columnDate)
This would essentially look for all future and past dates using your #passedInDate (DateTime.Now) as the qualifier or base date. I'm using seconds as the time interval to compare in my example, but you can change that to whatever makes the most sense for you.
Also, you shouldn't need to pass in DateTime.Now to SQL server, as you can use the built in GetDate() function.

Something like this should work:
SELECT TOP 1 * FROM MyTable ORDER BY ABS(DATEDIFF(DD, getdate(), DATE))
This should sort your rows by the closest date, past or future. If you need it more precise then just days, change DD to something else, as specified here

Related

sql select duplicates by ignore seconds in date format [duplicate]

Which method provides the best performance when removing the time portion from a datetime field in SQL Server?
a) select DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)
or
b) select cast(convert(char(11), getdate(), 113) as datetime)
The second method does send a few more bytes either way but that might not be as important as the speed of the conversion.
Both also appear to be very fast, but there might be a difference in speed when dealing with hundreds-of-thousands or more rows?
Also, is it possible that there are even better methods to get rid of the time portion of a datetime in SQL?
Strictly, method a is the least resource intensive:
a) select DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)
Proven less CPU intensive for the same total duration a million rows by someone with way too much time on their hands: Most efficient way in SQL Server to get a date from date+time?
I saw a similar test elsewhere with similar results too.
I prefer the DATEADD/DATEDIFF because:
varchar is subject to language/dateformat issues
Example: Why is my CASE expression non-deterministic?
float relies on internal storage
it extends to work out first day of month, tomorrow, etc by changing "0" base
Edit, Oct 2011
For SQL Server 2008+, you can CAST to date i.e. CAST(getdate() AS date). Or just use date datatype so no time to remove.
Edit, Jan 2012
A worked example of how flexible this is: Need to calculate by rounded time or date figure in sql server
Edit, May 2012
Do not use this in WHERE clauses and the like without thinking: adding a function or CAST to a column invalidates index usage. See number 2 here Common SQL Programming Mistakes
Now, this does have an example of later SQL Server optimiser versions managing CAST to date correctly, but generally it will be a bad idea ...
Edit, Sep 2018, for datetime2
DECLARE #datetime2value datetime2 = '02180912 11:45' --this is deliberately within datetime2, year 0218
DECLARE #datetime2epoch datetime2 = '19000101'
select DATEADD(dd, DATEDIFF(dd, #datetime2epoch, #datetime2value), #datetime2epoch)
In SQL Server 2008, you can use:
CONVERT(DATE, getdate(), 101)
Of-course this is an old thread but to make it complete.
From SQL 2008 you can use DATE datatype so you can simply do:
SELECT CONVERT(DATE,GETDATE())
In SQL Server 2008, there is a DATE datetype (also a TIME datatype).
CAST(GetDate() as DATE)
or
declare #Dt as DATE = GetDate()
SELECT CAST(FLOOR(CAST(getdate() AS FLOAT)) AS DATETIME)
...is not a good solution, per the comments below.
I would delete this answer, but I'll leave it here as a counter-example since I think the commenters' explanation of why it's not a good idea is still useful.
Here's yet another answer, from another duplicate question:
SELECT CAST(CAST(getutcdate() - 0.50000004 AS int) AS datetime)
This magic number method performs slightly faster than the DATEADD method. (It looks like ~10%)
The CPU Time on several rounds of a million records:
DATEADD MAGIC FLOAT
500 453
453 360
375 375
406 360
But note that these numbers are possibly irrelevant because they are already VERY fast. Unless I had record sets of 100,000 or more, I couldn't even get the CPU Time to read above zero.
Considering the fact that DateAdd is meant for this purpose and is more robust, I'd say use DateAdd.
SELECT CAST(CAST(GETDATE() AS DATE) AS DATETIME)
I really like:
[date] = CONVERT(VARCHAR(10), GETDATE(), 120)
The 120 format code will coerce the date into the ISO 8601 standard:
'YYYY-MM-DD' or '2017-01-09'
Super easy to use in dplyr (R) and pandas (Python)!
BEWARE!
Method a) and b) does NOT always have the same output!
select DATEADD(dd, DATEDIFF(dd, 0, '2013-12-31 23:59:59.999'), 0)
Output: 2014-01-01 00:00:00.000
select cast(convert(char(11), '2013-12-31 23:59:59.999', 113) as datetime)
Output: 2013-12-31 00:00:00.000
(Tested on MS SQL Server 2005 and 2008 R2)
EDIT: According to Adam's comment, this cannot happen if you read the date value from the table, but it can happen if you provide your date value as a literal (example: as a parameter of a stored procedure called via ADO.NET).
See this question:
How can I truncate a datetime in SQL Server?
Whatever you do, don't use the string method. That's about the worst way you could do it.
Already answered but ill throw this out there too...
this suposedly also preforms well but it works by throwing away the decimal (which stores time) from the float and returning only whole part (which is date)
CAST(
FLOOR( CAST( GETDATE() AS FLOAT ) )
AS DATETIME
)
second time I found this solution... i grabbed this code off
CAST(round(cast(getdate()as real),0,1) AS datetime)
This method does not use string function. Date is basically a real datatype with digits before decimal are fraction of a day.
this I guess will be faster than a lot.
For me the code below is always a winner:
SELECT CONVERT(DATETIME, FLOOR(CONVERT(FLOAT,GETDATE())));
select CONVERT(char(10), GetDate(),126)
Strip time on inserts/updates in the first place. As for on-the-fly conversion, nothing can beat a user-defined function maintanability-wise:
select date_only(dd)
The implementation of date_only can be anything you like - now it's abstracted away and calling code is much much cleaner.
I think you mean
cast(floor(cast(getdate()as float))as datetime)
real is only 32-bits, and could lose some information
This is fastest
cast(cast(getdate()+x-0.5 as int)as datetime)
...though only about 10% faster(about 0.49 microseconds CPU vs. 0.58)
This was recommended, and takes the same time in my test just now:
DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)
In SQL 2008, the SQL CLR function is about 5 times faster than using a SQL function would be, at 1.35 microseconds versus 6.5 microsections, indicating much lower function-call overhead for a SQL CLR function versus a simple SQL UDF.
In SQL 2005, the SQL CLR function is 16 times faster, per my testing, versus this slow function:
create function dateonly ( #dt datetime )
returns datetime
as
begin
return cast(floor(cast(#dt as float))as int)
end
How about select cast(cast my_datetime_field as date) as datetime)? This results in the same date, with the time set to 00:00, but avoids any conversion to text and also avoids any explicit numeric rounding.
I think that if you stick strictly with TSQL that this is the fastest way to truncate the time:
select convert(datetime,convert(int,convert(float,[Modified])))
I found this truncation method to be about 5% faster than the DateAdd method. And this can be easily modified to round to the nearest day like this:
select convert(datetime,ROUND(convert(float,[Modified]),0))
Here I made a function to remove some parts of a datetime for SQL Server. Usage:
First param is the datetime to be stripped off.
Second param is a char:
s: rounds to seconds; removes milliseconds
m: rounds to minutes; removes seconds and milliseconds
h: rounds to hours; removes minutes, seconds and milliseconds.
d: rounds to days; removes hours, minutes, seconds and milliseconds.
Returns the new datetime
create function dbo.uf_RoundDateTime(#dt as datetime, #part as char)
returns datetime
as
begin
if CHARINDEX( #part, 'smhd',0) = 0 return #dt;
return cast(
Case #part
when 's' then convert(varchar(19), #dt, 126)
when 'm' then convert(varchar(17), #dt, 126) + '00'
when 'h' then convert(varchar(14), #dt, 126) + '00:00'
when 'd' then convert(varchar(14), #dt, 112)
end as datetime )
end
Just in case anyone is looking in here for a Sybase version since several of the versions above didn't work
CAST(CONVERT(DATE,GETDATE(),103) AS DATETIME)
Tested in I SQL v11 running on Adaptive Server 15.7
If possible, for special things like this, I like to use CLR functions.
In this case:
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlDateTime DateOnly(SqlDateTime input)
{
if (!input.IsNull)
{
SqlDateTime dt = new SqlDateTime(input.Value.Year, input.Value.Month, input.Value.Day, 0, 0, 0);
return dt;
}
else
return SqlDateTime.Null;
}
I, personally, almost always use User Defined functions for this if dealing with SQL Server 2005 (or lower version), however, it should be noted that there are specific drawbacks to using UDF's, especially if applying them to WHERE clauses (see below and the comments on this answer for further details). If using SQL Server 2008 (or higher) - see below.
In fact, for most databases that I create, I add these UDF's in right near the start since I know there's a 99% chance I'm going to need them sooner or later.
I create one for "date only" & "time only" (although the "date only" one is by far the most used of the two).
Here's some links to a variety of date-related UDF's:
Essential SQL Server Date, Time and DateTime Functions
Get Date Only Function
That last link shows no less than 3 different ways to getting the date only part of a datetime field and mentions some pros and cons of each approach.
If using a UDF, it should be noted that you should try to avoid using the UDF as part of a WHERE clause in a query as this will greatly hinder performance of the query. The main reason for this is that using a UDF in a WHERE clause renders that clause as non-sargable, which means that SQL Server can no longer use an index with that clause in order to improve the speed of query execution. With reference to my own usage of UDF's, I'll frequently use the "raw" date column within the WHERE clause, but apply the UDF to the SELECTed column. In this way, the UDF is only applied to the filtered result-set and not every row of the table as part of the filter.
Of course, the absolute best approach for this is to use SQL Server 2008 (or higher) and separate out your dates and times, as the SQL Server database engine is then natively providing the individual date and time components, and can efficiently query these independently without the need for a UDF or other mechanism to extract either the date or time part from a composite datetime type.
I would use:
CAST
(
CAST(YEAR(DATEFIELD) as varchar(4)) + '/' CAST(MM(DATEFIELD) as varchar(2)) + '/' CAST(DD(DATEFIELD) as varchar(2)) as datetime
)
Thus effectively creating a new field from the date field you already have.

How to get the latest record from a database in ASP.Net using C#?

I want to get the latest record from my database
Below is my query
select * from tablename order by date desc, time desc
My Issues
My query show uncertain behavior, sometimes it works properly in website but sometimes is does not give the desired result. It happen because of time part
Example
2:00 pm and 2:00 AM how to compare this time?
The exact Query is for getting very latest row
select Top 1 * from tablename order by date desc, time desc
so if you´re datatype is really VARCHAR you can convert it to date and time in the order by clause
begin
declare #time1 time
declare #time2 time
declare #test table(
mytime varchar(max),
mydate varchar(max)
)
insert into #test VALUES('2:00 pm', '10-10-2010')
insert into #test VALUES('2:00 am', '08-05-2009')
SELECT * FROM #test ORDER BY CONVERT(date, mydate) DESC, CONVERT(time, mytime) DESC
end
but i would suggest to change your table-structure, to have only one DateTime Column!
Or at least change the DataType to TIME and DATE!
Unless you have some special requirement, it will be better to use only one column of datetime type to store date and time.
If two columns are must, you can store time in 24-hour format.
Try this. Convert the date and time into a datetime and then order by that.
select *
from tablename
order by cast(date AS DATETIME) + cast(time AS DATETIME)
Select Top 1 ColumnName from dbo.TableName Order by date,time desc
I think u should convert the time in AM/PM to 24-hrs format. Check this out http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_date-format

select in sql with specific format of date

I have a website project which selects dates from database. the database stores the date in this format "2013-01-02 00:00:00.000". but when I select the date, I want to use the format "11/06/2013" - "dd/mm/yyyy"
here is my select
-- I am trying to pass "dd/mm/yyyy"
select date from Currencies where date = '11/06/2013'
but this doesnt work. if I change my where clause as below, it works...
-- if I pass "mm/dd/yyyy" , it works
select date from Currencies where date = '06/11/2013'
but I must pass "dd/mm/yyyy", how can I do that?
Try this one
SELECT date FROM Currencies WHERE date = convert(datetime, '11/06/2013 00:00:00', 103)
You should avoid handling variable syntax inside your sql statements and use parameterized queries instead
check this out.

SQL Query with Long Date Time?

I am trying to pass a SQL query through c# , currently it is based on just the day month and year with time always set to 0 EG 1997-10-28 00.00.00.000 which is great as the time never changes it easy for me to just Select Where date equals the calendar date.
However with the Start Field , the time is different on each record , eg 1899-12-30 14.14:00.00.000 , 1899-12-30 15.14:30.00.000 . (Seconds downwards are always the same) .
So I need to have a query that will return all the results of the selected date on the "Start" field . How would I do this?.
E.G IF i click the calendar which passes 1997-10-28 00.00.00.000 , I would like the results of every time in that day!. How do I go about that?.
Thanks for any input.
EDIT: Is there a way to format the date that i have in SQL ?. This comes from an old access database!. and as you can see above it is 1899-12-30 ?. not 1998 , I don't know why this has happened!.
WHERE DATEDIFF(dd, your_start_field, #your_param) = 0
You need to select all record between today and tomorrow without including tomorrow's date.
WHERE EventDate >= StartDate AND EventDate < DATEADD(d, 1, StartDate)
Can you not just query the date part. I think this should work...
SELECT * FROM Table1 WHERE StartDate = '1997-10-28'
EDIT: Above may not work but following should cover needs
SELECT * FROM Table1 WHERE StartDate >= '1997-10-28 00:00:00.000' AND StartDate < '1997-10-29 00:00:00.000'
(notice the second date is the following date)
This SQL DATEADD(d,datediff(d,0,startdate),startdate) will convert a date with time to just the date;
eg
Select field1,field2 from mytable where DATEADD(d,datediff(d,0,startdate),startdate)='1997-10-28'

Casting a double to a DateTime type is off by 2 days?

I store datetime values in the database as sql float type (Converted from an DateTime.OADate) for a myriad of reasons however in certain circumstances it is nice to get a human readable date/time column back from the database. I have found that I can execute the statement
SELECT CAST (timerecorded_utc as DATETIME) FROM tablename
and it will give me the date time string I am looking for but it seems to be off by exactly 2 days. I realize I can just modify the statement (since in time represented as a double 1 day = 1.0) to be
SELECT CAST (timerecorded_utc-2.0 as DATETIME) FROM tablename
BUT I was wondering if this is consistent AND it seems to me there is some reason for the discrepancy that I am missing.
It's because the epochs the dates use are different.
SQL Server's DATETIME uses 01/01/1900 00:00:00 as the epoch, which you can see by running the following query: SELECT CAST(0 AS DATETIME)
OADate is a bit odd, as it could have an epoch of 30/12/1899 00:00:00 or 31/12/1899 00:00:00 depending on whether you believe the Visual Basic or Excel guys, respectively. It would appear that from your two day difference, the .NET version goes with the 30th.
So, epoch off by two days gives two days difference in the outcome when you convert between the two types of date via a raw number.
Epic Epochs... Here is my TSQL solution in SQL Server using the built in
"DateAdd" function:
Select DateAdd(DAY, cast([ENDING DATE] as decimal(10,0)), '12/30/1899')
from YourTable
In my case I was importing a string saved in Excel via C# Core App and uploading to a SQL Server database so my [Ending Date] is a string which I casted as a decimal with no precision as I only needed the actual date, and not the time of day. As #GregBeech mentioned, your base date might be '12/31/1899'.

Categories

Resources