Why is '=' operator not working on comparing Datetime? - sql

I am trying to fetch records only of the current day. I have used the = operator to compare the date but it is not working, if I subtract 1 from the current date and then use >= operator then it works.
I am putting both queries here.
This code works:
1 = (
CASE WHEN ISNULL(DO.CREATEDON, '') >= GETDATE()-1
THEN 1
END
This code doesn't work:
1 = (
CASE WHEN ISNULL(DO.CREATEDON, '') = GETDATE()
THEN 1
END
Why is the latter code not working?

GETDATE() returns a datetime, so (for me), right now, using GETDATE() returns something like 2021-01-19T09:43:27.123. It's therefore very unlikely the value in your column CREATEDON is going to be the same exact time that GETDATE() returns, accurate to the nearest 1/300 of a second.
If your column CREATEDON is a date and time value, use inclusive date ranges:
WHERE DO.CREATEDON >= CONVERT(date,GETDATE())
AND DO.CREATEDON < CONVERT(date,DATEADD(DAY, 1, GETDATE())
If CREATEDON is a date, then just CONVERT the value of GETDATE() to a date:
WHERE DO.CREATEDON = CONVERT(date,GETDATE())
Note that there's no need for the ISNULL, as is the value of NULL it is by definition not the value of GETDATE(). Also, converting'' to a date and time value is a little odd; but it would convert to 1900-01-01, which again, is not today. Adding an ISNULL on DO.CREATEDON in the WHERE will only harm the performance; don't do it.

Related

Yesterday into YYYYMMDD format in SQL Server

I'm looking to add in a condition to my already badly performing SQL code. I want to add in a filter where the date = yesterday (data type as INT).
For example
Select *
From table
Where Date = 20190930
How do I do this using GETDATE() - 1?
We need to be very clear about what data type you're using.
If you have a simple date value (no time component as part of the data type), things are pretty easy:
Select *
from table
where Date = DATEADD(day, -1, cast(current_timestamp as date))
If you have a DateTime or DateTime2 value, it's important to understand that all DateTime values have a time component that goes all the way down to milliseconds. This is true even when you expect the time component to always be at or near midnight. That can make straight equality comparisons difficult. Instead, you almost always need check within a specific range:
Select *
from table
where Date >= DATEADD(day, -1, cast(current_timestamp as date))
AND Date < cast(current_timestamp as date)
Here's your query.
Firstly, you need to cast your int date to a varchar before covenrting to datetime, to avoid an arithmetic flow error during conversion.
Secondly, you need to cast getdate() - 1 as date to truncate time to match your date field.
select *
from table
where cast((cast(date as varchar(8))as datetime) = cast(getdate() - 1 as date)
or
select *
from table
where cast((cast(date as varchar(8)) as date) = cast(dateadd(day,datediff(day,1,GETDATE()),0) as date)

Converting date and/or time from character string is failing

I have this query and I tried converting it to every format, I mean the date time etc but it doesn't work and throws error:
Conversion failed when converting date and/or time from character string.
SELECT W.Organization_ID,
W.NIT_No,
W.SchemeID,
OpeningDate,
OpeningTime,
GETDATE(),
WorkNo,
CONVERT(decimal(10, 2), W.Cost) AS Cost,
WorkName,
W.ExpiryDate as ExpiryDate,
CONVERT(VARCHAR,OpeningDate,106),
CASE WHEN
CONVERT(DATETIME, CONVERT(VARCHAR(20),OpeningDate,106) + ' '
+ CONVERT(VARCHAR(20),OpeningTime,108))< GETDATE()
THEN 1
ELSE 0 END AS OpeningVaild
FROM Works W
the CASE part throws error.
OpeningDate is of type Varchar and OpeningTime is of type Time.
Why?
You are converting just a TIME datatype not a DATETIME so you don't need to specify the style:
DECLARE #T TIME = '08:05:06';
SELECT CONVERT(VARCHAR(8), #T) AS [Time];
SELECT CAST(#T AS VARCHAR(8)) AS [Time];
Or since you are using CONVERT()pick the right style for TIME datatype which is 108 or 114, instead of 106
SELECT CONVERT(VARCHAR(8), #T, 108) AS [Time];
Update:
According to the error Msg, your problem is in the CASE part.
That because you are trying to concat a DATETIME with a VARCHAR datatype, look at here to what you'r converting:
CASE WHEN
CONVERT(DATETIME, CONVERT(VARCHAR(20),OpeningDate,106) + ' '
+ CONVERT(VARCHAR(20),OpeningTime,108))< GETDATE()
THEN 1
ELSE 0 END AS OpeningVaild
Also the column OpeningDate -according to the error Msg- is VARCHAR so your are convert a VARCHAR to VARCHAR then convert it again to DATETIME then you try to concatinate the DATETIME with the VARCHAR returned from converting OpeningTime column from TIMEto VARCHAR, then try to compare them with GETDATE() which is DATETIME datatype.
So you CASE should look like:
CASE WHEN
(
CAST(OpeningDate AS DATETIME) + -- VARCHAR to DATETIME
CAST(OpeningTime AS DATETIME) -- TIME to DATETIME
) < GETDATE()
THEN 1
ELSE 0 END AS OpeningVaild
A beside note, here in this line
CONVERT(VARCHAR,OpeningDate,106),
You are trying to convert a VARCHAR to VARCHAR and without specify the lenght too, so this line should be:
CONVERT(VARCHAR(10),CAST(OpeningDate AS DATE),106),
Finally, don't ever ever store DATE as VARCHAR, the DATE/ TIME/ DATEIME are there for a reason, so use them and all other datatypes wisely.
Here is a demo represent your issue, and how to fix it.
You can simplify this big time by changing the expression a little.
This way you don't have to convert and concatenate.
SELECT
CASE WHEN OpeningDate < GETDATE() - OpeningTime
THEN 1
ELSE 0 END AS OpeningVaild
Note I am assuming that Openingdate has the format dd-mon-yyyy. Otherwise you still need to convert it, but still shorter:
SELECT
CASE WHEN Convert(date, OpeningDate, 106) < GETDATE() - OpeningTime
THEN 1
ELSE 0 END AS OpeningVaild
So I understand the problem is with this part:
CASE WHEN CONVERT(DATETIME, CONVERT(VARCHAR(20),OpeningDate,106) + ' ' + CONVERT(VARCHAR(20),OpeningTime,108))< GETDATE() THEN 1 ELSE 0 END AS OpeningVaild
Update
Since I've first posted my answer it turns out that you store the opening date as varchar instead of date.
First, you should stop doing that. Never store dates in anything other than a Date column (unless you need them with time as well, and then use DateTime2).
For more information, read Aaron Bertrand's Bad habits to kick : choosing the wrong data type.
Assuming the data type of the column can't change, you wrote in the comments to the question:
#ZoharPeled: this is the format of openingdate 2017-04-10
Illustrating one of the problems caused by storing dates as strings - How can I, or anyone else for that matter, know if that's the 10th of April or the 4th of October? The answer is we can't.
So, assuming it's the 10th of April, you can convert it to DateTime using convert with 126 as the style parameter:
CASE
WHEN CONVERT(DateTime, OpeningDate, 126) + CAST(OpeningTime As DateTime) < GETDATE() THEN
1
ELSE
0
END As OpeningVaild
First version:
Assuming that the data type of OpeningDate is Date and the data type of OpeningTime is Time, Seems like you are attempting to figure out if these columns combination into a DateTime is before the current DateTime.
Instead of converting them into strings and back to DateTime, you can cast both to DateTime and simply add them together:
CASE
WHEN CAST(OpeningDate As DateTime) + CAST(OpeningTime As DateTime) < GETDATE() THEN
1
ELSE
0
END As OpeningVaild
Another option would be to use GETDATE() twice. I don't think it should matter in the select clause, but in the where clause it's important to use this option since the first one will make these columns non-seargable, meaning the database engine will not be able to use any indexes that might help the execution plan of the statement:
CASE
WHEN OpeningDate < CAST(GETDATE() AS DATE)
OR
(
OpeningDate = CAST(GETDATE() AS DATE)
AND OpeningTime <= CAST(GETDATE() AS TIME)
) THEN
1
ELSE
0
END AS OpeningVaild
That being said, your query also have CONVERT(VARCHAR,OpeningDate,106) - The 106 style returns a string representation of the date as dd mon yyyy - meaning 11 chars - so change that to CONVERT(CHAR(11),OpeningDate,106) Note that using varchar without specifying the length defaults to 30, which is not a problem in this case since it's more than he 11 chars you need, but it's a bad habit to not specify length and you should kick it.

SQL IF statement for todays date

I'm trying to create a condition for my SQL, that shows a 1 if that row reflects today's day.
case when A.EntryDate = GETDATE() then '1' else '0' end as Today
That's accepted but it doesn't show anything but zeros. I've only worked with Access SQL and this one seems to dislike Date()
I've been looking all around for answers and I cannot seem to find one.
The GetDate() method return datetime. To compare today's date you need to convert datetime to date.
case when cast(A.EntryDate as date) = cast(getdate() as date) then 1 else 0 end

SQL Server : today is not equal to today

Maybe I'm making an obvious mistake but can anyone explain what's going on here? I was running a query where the table's field is datetime and the query I was running was something like
SELECT *
FROM Table
WHERE DateTimeColumn <= '20170714'
and I noticed the output excluded the records where DateTimeColumn is '20170714' they finished at '20170713'
Below I was expecting all 3 IIF to fall into true.
DECLARE #d1 DATE = '20170714'
SELECT IIF(GETDATE() <= #d1, 'GETDATE() Less than or equal to #d1', 'GETDATE() **NOT** Less than or equal to #d1')
DECLARE #d2 DATE = '20170714 11:59:59'
SELECT IIF(GETDATE() <= #d2, 'GETDATE() Less than or equal to #d2', 'GETDATE() **NOT** Less than or equal to #d2')
DECLARE #tomorrow DATE = '20170715'
SELECT IIF(GETDATE() <= #tomorrow, 'GETDATE() Less than or equal to #tomorrow', 'GETDATE() **NOT** Less than or equal to #tomorrow')
Just use less than 2017-07-15 (tomorrow)
SELECT *
FROM Table
WHERE DateTimeColumn < '20170715'
If wanting to use getdate, try this:
SELECT *
FROM Table
WHERE DateTimeColumn < dateadd(day,1,cast(getdate() as date))
Use sargable predicates. DO NOT convert your data to suit a filtering predicate, this affects index access and/or requires unnecessary calculations. Here is a former answer on the similar question.
Also note that 23:59:59 is NOT the end of a day, it is one full second short of a full day: datetime is accurate to approx 3 milliseconds and datetime2 is even more sensitive.
Can you just change the query like this :
SELECT *
FROM Table
WHERE CONVERT(date, DateTimeColumn) <= '20170714'
It would return all the records less that 14 and record with date 14.

To get date from datetime in sql

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?
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.
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.
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())
The simplest solution might be :
SELECT CAST(GETDATE() as DATE)
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.