How to compare datetime in SQL Server in where clause - sql-server

I have CreatedDate as datetime column in my database table. I want to fetch the rows where CreatedDate and current time difference is more than 1 hour

Select * from TableName where (DateDiff(hh,CreatedDate,GetDate())>1

Answer by #Amit Singh works if you only care about the hour value itself, versus any 60 minute period.
The problem with using DATEDIFF(hh) that way is that times of 13:01 and 14:59 are only one "hour" apart.
Like:
select datediff(hh,'1/1/2001 13:59','1/1/2001 14:01')
I think doing this would address that issue:
declare #cd datetime='9/12/2013 03:10';
declare #t table(id int,CreatedDate datetime);
insert #t select 1,'9/12/2013 02:50';
insert #t select 2,'9/12/2013 02:05';
select * from #t where #cd>(DateAdd(hh,1,CreatedDate))

Dan Bellandi raises a valid point, but if it really matters if the dates should be 60 minutes apart, then just check if they are 60 minutes apart:
SELECT * FROM TableName WHERE DATEDIFF(MINUTE, DateColumnName, GETDATE()) >= 60

If you don't expect any rows created in the future...
where CreatedDate < dateadd(hour, -1, getdate())

CREATE TABLE trialforDate
(
id INT NULL,
NAME VARCHAR(20) NULL,
addeddate DATETIME NULL
)
INSERT INTO trialforDate VALUES (1,'xxxx',GETDATE())
INSERT INTO trialforDate VALUES (2,'yyyy',GETDATE())
INSERT INTO trialforDate VALUES (1,'zzzz','2013-09-12 11:20:40.533')
SELECT *
FROM trialforDate
WHERE GETDATE() > DATEADD(HOUR, 1, addeddate)

C# Code
DateTime param1= System.DateTime.Now;
DateTime param2= System.DateTime.Now.AddHours(1);
SQL Query:
SELECT * FROM TableName WHERE CreatedDate = param1 AND CreatedDate =param2;

Related

Dynamic SQL to randomize all datetime columns in a database

I'm having trouble figuring out how to use a dynamic SQL Server query to change the datetime fields in my database, called OnlineStore, to be random and in the current year.
It should be noted that this relates to homework. My class is fairly unstructured, so I'm having a hard time knowing where to go from here.
My question is: How can I write a dynamic SQL Server query that may use loops or table variables and takes the 2 datetime columns in my database (Product.LastOrderDate, Orders.OrderDate) and assigns each row a random date in the current year?
This is what I have so far. I'm open to any changes.
Declare #SQL varchar(max) = '
Declare #D1 float = cast(cast(''2017-01-01 00:00:00'' as datetime) as float);
Declare #D2 float = cast(cast(''2017-12-31 23:59:59'' as datetime) as float);
Based on this answer I came up with the following. It randomly adds n seconds to the date 2017-01-01 capped at the number of seconds in 2017.
The first bit is just me generating a table with 50 rows, all 2017-01-01.
You'll want to focus on the parts from update on...
if object_id('tempdb..#test') is not null drop table #test
create table #test (orderDate datetime)
-- add 50 rows to test table
;with x as
(
select 1 as t
union all
select t+1
from x
)
insert into #test
select top 50 '2017-01-01'
from x
option(maxrecursion 50)
--select * from #test
update t
set OrderDate = dateadd(second,ABS(CHECKSUM(NewId())) % datediff(second,'2017-01-01 00:00:00','2017-12-31 23:59:59'),'2017-01-01 00:00:00')
from #test t
select * from #test
Based on this answer: https://stackoverflow.com/a/18408615
This gets you almost all the way there for generating a random date, I capped the days at 28 due to February being February.
select cast('2017-' + CAST(ABS(Checksum(NEWID()) % 12) + 1 AS varchar(2)) + '-' + CAST(ABS(Checksum(NEWID()) % 28) + 1 AS varchar(2)) as date)
You can adapt this to fit your needs.

SQL: How to query all data within the month from the given date?

I have a table tbl1 of ID Numbers and their corresponding Membership Date.
I want to create a stored procedure which has a #member_date parameter provided. I want the procedure to get the month and year of #member_date to get all the records covered by the month and date
ID_Number Member_Date
10001 12/1/2015
10002 12/15/2015
10003 10/9/2015
10004 12/13/2014
Something like below:
#member_date = '12/25/2015'
Select * from tbl1 where month(Member_Date)=12 and year(Member_Date)=2015
Output:
ID_Number Member_Date
10001 12/1/2015
10002 12/15/2015
Thank you for your help
Greatly appreciated
Still I am not getting you proper, but I think you want something like below,
CREATE TABLE RYANTABLE (ID_NUMBER INT, MEMBER_DATE DATE)
INSERT INTO RYANTABLE VALUES (10001,'12/1/2015')
INSERT INTO RYANTABLE VALUES (10002,'12/15/2015')
INSERT INTO RYANTABLE VALUES (10003,'10/9/2015')
INSERT INTO RYANTABLE VALUES (10004,'12/13/2014')
You need store procedure right like below ?
--EXEC RyanProcedure '12/25/2015'
CREATE PROCEDURE RyanProcedure
#member_date DATE
AS
BEGIN
DECLARE #MONTH AS INT=MONTH(#member_date)
DECLARE #Year AS INT=YEAR(#member_date)
SELECT *
FROM RyanTable
WHERE (MONTH(Member_Date) = #MONTH
AND YEAR(Member_Date) = #Year)
OR (Member_Date = #member_date)
END
you can use
DATE_FORMAT(<date>, <date_format>)
for example
SELECT * FROM TBL1 WHERE DATE_FORMAT(Member_Date, '%Y%m') = '201512'
%Y Year, numeric, four digits,
%m Month, numeric (00-12)
for date format, you can see in here
You should make your query Sargable for best performance
DECLARE #member_date date= '12/25/2015'
SELECT *
FROM
tbl1
WHERE
Member_Date >= dateadd(month, datediff(month, 0, #member_date), 0)
Member_Date < dateadd(month, datediff(month, -1, #member_date), 0)

date comparison in sql server

I am trying to display records which have their date (I have a column Date in table) 30 days back from today's date. And once it gets displayed I need to make a new record by adding details with Date= today's date..
I tried this:
select * from
paymenthist
where
Date = CONVERT(datetime, CONVERT(varchar, DATEADD(day, -30, GETDATE()), 101))
But all records are getting displayed..
Ok, I admit the way I suggested may be inefficient, but if one is a datetime and the other is a date then I believe this will be more efficient than the >= <= approach because SQL is often not great at utilising indexes for queries like this, and under the covers a datetime is actually a floating point, so for pure efficiency, try this:
CREATE TABLE ##PaymentHistory
(
ID INT IDENTITY,
[Date] DATETIME,
Col1 INT,
Col2 INT
)
INSERT INTO ##PaymentHistory([Date],Col1,Col2)
VALUES(FLOOR(CAST(GETDATE() -29 AS FLOAT) ) ,1,1)
, (FLOOR(CAST(GETDATE() -30 AS FLOAT) ) ,2,2)
, (FLOOR(CAST(GETDATE() -31 AS FLOAT) ) ,3,3)
SET IDENTITY_INSERT ##PaymentHistory ON
INSERT INTO ##PaymentHistory(ID, [Date], Col1, Col2)
SELECT ID, GETDATE(), Col1, Col2
FROM ##PaymentHistory
WHERE CAST(Date AS FLOAT) = FLOOR(CAST(GETDATE() -30 AS FLOAT) )
SET IDENTITY_INSERT ##PaymentHistory OFF
It depends somewhat on the datatype of the date column, but try this.
select * from paymenthist where cast(Date as date) = cast(DATEADD(day, -30, GETDATE()) as date)

T-SQL query with date range

I have a fairly weird 'bug' with a simple query, and I vaguely remember reading the reason for it somewhere a long time ago but would love someone to refresh my memory.
The table is a basic ID, Datetime table.
The query is:
select ID, Datetime from Table where Datetime <= '2010-03-31 23:59:59'
The problem is that the query results include results where the Datetime is '2010-04-01 00:00:00'. The next day. Which it shouldn't.
Anyone?
Cheers
Moo
Take a look at How Are Dates Stored In SQL Server? and How Does Between Work With Dates In SQL Server?
If that is a smalldatetime it has 1 minute precision so if rounds up, for datetime it is 300 miliseconds
example
DECLARE #d DATETIME
SELECT #d = '2001-12-31 23:59:59.999'
SELECT #d
2002-01-01 00:00:00.000
DECLARE #d DATETIME
SELECT #d = '2001-12-31 23:59:59.998'
SELECT #d
2001-12-31 23:59:59.997
Always use less than next day at midnight, in your case
< '20100401'
try doing it like:
select ID, Datetime from Table where Datetime < '2010-04-01'
I always floor the datetime and increment the day and just use "<" less than.
to floor a datetime to just the day use:
SELECT DATEADD(day,DATEDIFF(day,0, GETDATE() ),0)
you can easily increment a datetime by using addition:
SELECT GETDATE()+1
by using the '23:59:59' you can miss rows, try it out:
DECLARE #YourTable table (RowID int, DateOf datetime)
INSERT INTO #YourTable VALUES (1,'2010-03-31 10:00')
INSERT INTO #YourTable VALUES (2,'2010-03-31')
INSERT INTO #YourTable VALUES (3,'2010-03-31 23:59:59')
INSERT INTO #YourTable VALUES (4,'2010-03-31 23:59:59.887')
INSERT INTO #YourTable VALUES (5,'2010-04-01')
INSERT INTO #YourTable VALUES (6,'2010-04-01 10:00')
select * from #YourTable where DateOf <= '2010-03-31 23:59:59'
OUTPUT
RowID DateOf
----------- -----------------------
1 2010-03-31 10:00:00.000
2 2010-03-31 00:00:00.000
3 2010-03-31 23:59:59.000
(3 row(s) affected
this query is wrong, because it does not find the missed rowID=4 record.
if you try to fix this with:
select * from #YourTable where DateOf <= '2010-03-31 23:59:59.999'
then RowID=5 will be included as well, which is wrong.
It's very odd that you are seeing that; I don't know why. But I will suggest that you write the query this way instead:
select ID, Datetime from Table where Datetime < '2010-04-01'

Compare a date string to datetime in SQL Server?

In SQL Server I have a DATETIME column which includes a time element.
Example:
'14 AUG 2008 14:23:019'
What is the best method to only select the records for a particular day, ignoring the time part?
Example: (Not safe, as it does not match the time part and returns no rows)
DECLARE #p_date DATETIME
SET #p_date = CONVERT( DATETIME, '14 AUG 2008', 106 )
SELECT *
FROM table1
WHERE column_datetime = #p_date
Note: Given this site is also about jotting down notes and techniques you pick up and then forget, I'm going to post my own answer to this question as DATETIME stuff in MSSQL is probably the topic I lookup most in SQLBOL.
Update Clarified example to be more specific.
Edit Sorry, But I've had to down-mod WRONG answers (answers that return wrong results).
#Jorrit: WHERE (date>'20080813' AND date<'20080815') will return the 13th and the 14th.
#wearejimbo: Close, but no cigar! badge awarded to you. You missed out records written at 14/08/2008 23:59:001 to 23:59:999 (i.e. Less than 1 second before midnight.)
Technique 1:
DECLARE #p_date DATETIME
SET #p_date = CONVERT( DATETIME, '14 AUG 2008', 106 )
SELECT *
FROM table1
WHERE column_datetime >= #p_date
AND column_datetime < DATEADD(d, 1, #p_date)
The advantage of this is that it will use any index on 'column_datetime' if it exists.
In SQL Server 2008, you could use the new DATE datatype
DECLARE #pDate DATE='2008-08-14'
SELECT colA, colB
FROM table1
WHERE convert(date, colDateTime) = #pDate
#Guy. I think you will find that this solution scales just fine. Have a look at the query execution plan of your original query.
And for mine:
Just compare the year, month and day values.
Declare #DateToSearch DateTime
Set #DateToSearch = '14 AUG 2008'
SELECT *
FROM table1
WHERE Year(column_datetime) = Year(#DateToSearch)
AND Month(column_datetime) = Month(#DateToSearch)
AND Day(column_datetime) = Day(#DateToSearch)
Something like this?
SELECT *
FROM table1
WHERE convert(varchar, column_datetime, 111) = '2008/08/14'
Technique 2:
DECLARE #p_date DATETIME
SET #p_date = CONVERT( DATETIME, '14 AUG 2008', 106 )
SELECT *
FROM table1
WHERE DATEDIFF( d, column_datetime, #p_date ) = 0
If the column_datetime field is not indexed, and is unlikely to be (or the index is unlikely to be used) then using DATEDIFF() is shorter.
Good point about the index in the answer you accepted.
Still, if you really search only on specific DATE or DATE ranges often, then the best solution I found is to add another persisted computed column to your table which would only contain the DATE, and add index on this column:
ALTER TABLE "table1"
ADD "column_date" AS CONVERT(DATE, "column_datetime") PERSISTED
Add index on that column:
CREATE NONCLUSTERED INDEX "table1_column_date_nu_nci"
ON "table1" ( "column_date" ASC )
GO
Then your search will be even faster:
DECLARE #p_date DATE
SET #p_date = CONVERT( DATE, '14 AUG 2008', 106 )
SELECT *
FROM table1
WHERE column_date = #p_date
I normally convert date-time to date and compare them, like these:
SELECT 'Same Date' WHERE CAST(getDate() as date) = cast('2/24/2012 2:23 PM' as date)
or
SELECT 'Same Date' WHERE DATEDIFF(dd, cast(getDate() as date), cast('2/24/2012 2:23 PM' as date)) = 0
This function Cast(Floor(Cast(GetDate() As Float)) As DateTime) returns a datetime datatype with the time portion removed and could be used as so.
Select
*
Table1
Where
Cast(Floor(Cast(Column_DateTime As Float)) As DateTime) = '14-AUG-2008'
or
DECLARE #p_date DATETIME
SET #p_date = Cast('14 AUG 2008' as DateTime)
SELECT *
FROM table1
WHERE Cast(Floor(Cast(column_datetime As Float)) As DateTime) = #p_date
How to get the DATE portion of a DATETIME field in MS SQL Server:
One of the quickest and neatest ways to do this is using
DATEADD(dd, DATEDIFF( dd, 0, #DAY ), 0)
It avoids the CPU busting "convert the date into a string without the time and then converting it back again" logic.
It also does not expose the internal implementation that the "time portion is expressed as a fraction" of the date.
Get the date of the first day of the month
DATEADD(dd, DATEDIFF( dd, -1, GetDate() - DAY(GetDate()) ), 0)
Get the date rfom 1 year ago
DATEADD(m,-12,DATEADD(dd, DATEDIFF( dd, -1, GetDate() - DAY(GetDate()) ), 0))
I know this isn't exactly how you want to do this, but it could be a start:
SELECT *
FROM (SELECT *, DATEPART(yy, column_dateTime) as Year,
DATEPART(mm, column_dateTime) as Month,
DATEPART(dd, column_dateTime) as Day
FROM table1)
WHERE Year = '2008'
AND Month = '8'
AND Day = '14'
SELECT *
FROM table1
WHERE CONVERT(varchar(10),columnDatetime,121) =
CONVERT(varchar(10),CONVERT('14 AUG 2008' ,smalldatetime),121)
This will convert the datatime and the string into varchars of the format "YYYY-MM-DD".
This is very ugly, but should work
Date can be compared in sqlserver using string comparision:
e.g.
DECLARE #strDate VARCHAR(15)
SET #strDate ='07-12-2010'
SELECT * FROM table
WHERE CONVERT(VARCHAR(15),dtInvoice, 112)>= CONVERT(VARCHAR(15),#strDate , 112)
DECLARE #Dat
SELECT *
FROM Jai
WHERE
CONVERT(VARCHAR(2),DATEPART("dd",Date)) +'/'+
CONVERT(VARCHAR(2),DATEPART("mm",Date)) +'/'+
CONVERT(VARCHAR(4), DATEPART("yy",Date)) = #Dat
The best way is to simply extract the date part using the SQL DATE() Function:
SELECT *
FROM table1
WHERE DATE(column_datetime) = #p_date;
SELECT * FROM tablename
WHERE CAST(FLOOR(CAST(column_datetime AS FLOAT))AS DATETIME) = '30 jan 2012'
SELECT CONVERT(VARCHAR(2),DATEPART("dd",doj)) +
'/' + CONVERT(VARCHAR(2),DATEPART("mm",doj)) +
'/' + CONVERT(VARCHAR(4),DATEPART("yy",doj)) FROM emp
There are many formats for date in SQL which are being specified. Refer https://msdn.microsoft.com/en-in/library/ms187928.aspx
Converting and comparing varchar column with selected dates.
Syntax:
SELECT * FROM tablename where CONVERT(datetime,columnname,103)
between '2016-03-01' and '2016-03-03'
In CONVERT(DATETIME,COLUMNNAME,103) "103" SPECIFIES THE DATE FORMAT as dd/mm/yyyy
In sqlserver
DECLARE #p_date DATE
SELECT *
FROM table1
WHERE column_dateTime=#p_date
In C#
Pass the short string of date value using ToShortDateString() function.
sample:
DateVariable.ToShortDateString();

Resources