How do I compare 2 dates in SQL Server - sql-server

I have a string 2021-02-23T06:58:51 that I want to check if it is greater than another date. When I do the below I get an error. Tried CAST still the same error.
select convert(smalldatetime, '2021-02-23T06:58:51') > convert(smalldatetime, GETDATE())
Started executing query at Line 1
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '>'.
Total execution time: 00:00:00.040

As I said in the comments, columns need to be defined as a scalar expression. The expression you have is not a scalar expression, it is a boolean expression:
convert(smalldatetime, '2021-02-23T06:58:51') > convert(smalldatetime, GETDATE())
This doesn't tell SQL Server what to display, and would be an expression you would normally find in the WHERE. I.e. Display rows where the value of {column} is greater than the current date and time.
What you likely want is a CASE expression or IIF:
SELECT CASE WHEN '2021-02-23T06:58:51' > GETDATE() THEN 1 END 0 END;
SELECT IIF('2021-02-23T06:58:51' > GETDATE(),1,0);

Is this what you want?
select IIF(convert(smalldatetime, '2021-02-23T06:58:51') > convert(smalldatetime, GETDATE()), 'True','False')

Related

Getting error when using the Datediff Function

Error is : SQL compilation error: error line 1 at position 8 Invalid argument types for function 'DATE_DIFFDATEINYEARS': (NUMBER(1,0), DATE)
SQL i wrote : Select DATEDIFF (YEAR,0, CURRENT_DATE())
Please use below code:
select DATEDIFF(year, '1900-01-01', CURRENT_TIMESTAMP())
The second argument (parameter) into the function should be a date (or timestamp) as well as the third.
https://docs.snowflake.net/manuals/sql-reference/functions/datediff.html
example as follows:
select datediff(year, current_date(), current_date());

SQL-SERVER - CASE error - CASE in specific source doesn't work

I am working on a query where i want the average temperature of a whole month, but i have a challenge. When the new year starts the Month is 1 and i can't use the command:
MONTH(TimestampUTC) = MONTH(DATEADD(MONTH, -1, GETDATE()))
Because month 1 minus 1 is month 0.
Therefor i wan't to use a case expression to make my code work.
When i run the query below i get the following error:
Msg 156, Level 15, State 1, Line 6
Incorrect syntax near the keyword 'CASE'.
Ofcourse i want the following query to work. Can someone help me?
SELECT AVG(Value) AS AVG_temp
FROM(
SELECT Value, TimestampUTC
WHERE SourceName = 'Buitentemperatuur'
CASE
WHEN MONTH(TimestampUTC) = 1
THEN MONTH(TimestampUTC) = MONTH(DATEADD(MONTH, +11, GETDATE()))
and YEAR(TimestampUTC) = YEAR(DATEADD(YEAR, -1, GETDATE()))
ELSE
MONTH(TimestampUTC) = MONTH(DATEADD(MONTH, -1, GETDATE()))
and YEAR(TimestampUTC) = YEAR(DATEADD(YEAR, 0, GETDATE()))
END
FROM vDataLogChannelValue
) x
The program i work in is Microsoft SQL Server Management Studio 2014.
I already did some UNIT tests on the other parts of the code. When i add the CASE the error comes active and the code doesn't work anymore.
UPDATE:
Thank you for the respons it works now, but now i have the following warning which doesn't make sense to me, because it worked when i tested it when it wasn't in this query:
Msg 102, Level 15, State 1, Line 8
Incorrect syntax near '='.
It is about the following line:
THEN MONTH(TimestampUTC) = MONTH(DATEADD(MONTH, +11, GETDATE()))
You will have to have an AND keyword after the first WHERE clause. And then you will have to build another WHERE clause which uses the CASE statement.
Apart from that there should be now assignments in the THEN clauses.
Here is an example of what could work in terms of syntax:
SELECT Value, TimestampUTC
WHERE SourceName = 'Buitentemperatuur' AND SomethingElse =
CASE
WHEN MONTH(TimestampUTC) = 1
THEN 123
ELSE
234
END
FROM vDataLogChannelValue
) x

Error Convert String to DateTime

SELECT CONVERT(datetime,'17/05/2015 22:15:00',103)
output:
2015-05-17 22:15:00.000
I want include 2 column is Date+Time
Example: Colunm Date and Time
**Date** **Time**
17/05/2015 22:15:00
but Error Query
SELECT CONVERT(datetime,[Date]+' '+[Time],103) FROM LPTables
Conversion failed when converting date and/or time from character string.
Just add the time portion to the date portion:
SELECT DATEADD(ms, DATEDIFF(ms, '00:00:00', [Time]), CONVERT(DATETIME, [Date]))
FROM LPTables
This will give you accuracy to the millisecond.
Just enclose your columns with ().
SELECT CONVERT(datetime,([Date]+' '+[Time]),103) FROM LPTables
WHERE ISNULL([Date],'')!='' AND ISNULL([Time],'')!=''
Sample :

Multiple Boolean Expressions in Case When statement

Below is the part code that I am trying to make work... Essentially it will give me the date of the previous Monday if today is Monday. If today is not Monday then it will give me the date of the Monday of this week.
WHERE
CASE WHEN
DATEPART(dw,GETDATE()) = '1'
THEN
DateColumn >= DATEADD(wk,DATEDIFF(wk,0,GETDATE()) - 1,0)
ELSE
DateColumn >= DATEADD(wk,DATEDIFF(wk,0,GETDATE()),0)
END
However, when I run the code it says there is an incorrect syntax near '>'. I am not sure if it doesn't like me using multiple Boolean expressions or if there really is something wrong with that syntax.
You got the syntax slightly wrong; it should be:
WHERE
DateColumn >=
CASE WHEN DATEPART(dw,GETDATE()) = 1 -- datepart returns an integer, so no quotes
THEN DATEADD(wk,DATEDIFF(wk,0,GETDATE()) - 1,0)
ELSE DATEADD(wk,DATEDIFF(wk,0,GETDATE()),0)
END

SQL Server Function WIthin Case Statement

select top 10 *, case
when datediff(day,DateOfSale, getDate()) > 5 then '5'
when datediff(day,DateOfSale, getDate()) > 10 then '10'
... (more datediff clauses)
...
...
else '20'
end as jack
from Foo
Is SQL Server smart enough to evaluate the datediff function call once within the case statement and then use that value for every when clause? Or is the function is getting called 'n' times, where 'n' is the amount of when clauses?
It's hard to see how SQL Server could evaluate the call once. The call has a column as parameter and so has to be evaluated for every row.
Thus, your condition is better written like:
when DateOfSale < dateadd(day, -5, getdate()) then '5'
In this case the difference is small. Date calculations are cheap.
The classic example where the function call does matter is a where condition on a table with an index on the date column. For example, YourTable with an index on (dt). This query would allow an index to be used:
select * from YourTable where dt < dateadd(day, -5, getdate())
While this query would not:
select * from YourTable where datediff(day, DateOfSale, getDate()) > 5
It's puzzling that so many answers are mentioning indexes. Indeed, DATEDIFF is not SARGable, but that's completely irrelevant here as CASE WHEN doesn't cause the query optimizer in SQL Server to consider index usage (other than trying to find a covering scannable path). The candidacy of DATEDIFF-involved expressions for index pathing is completely irrelevant to this question, as far as I can tell.
It's pretty easy to demonstrate that SQL Server does, indeed, stop evaluating predicates inside CASE statements once the first true predicate is found.
To demonstrate that fact, let's cook up some sample data:
CREATE TABLE Diffy (SomeKey INTEGER NOT NULL IDENTITY(1,1), DateOfSale DATE);
DECLARE #ThisOne AS DATE;
SET #ThisONe = '2012-01-01';
WHILE #thisONe < '2013-01-01'
BEGIN
INSERT INTO Diffy (DateOfSale) VALUES(#ThisOne);
SET #ThisOne = DateAdd(d, 1, #ThisOne);
END;
Then, let's SELECT it in the pattern of the original question. Note that the original question specifies a TOP 10 clause without an ORDER BY clause, so the values we actually get back are random. But if we add a clause to the CASE that would poison evaluation, we can see what's happening:
SELECT TOP 10 *, CASE
WHEN datediff(day,DateOfSale, getDate()) > 5 then '5'
WHEN datediff(day,DateOfSale, getDate()) > 10 then '10'
WHEN 1/0 > 1then 'boom'
ELSE '20' END
AS Jack
FROM Diffy;
Note that if we ever evaluated 1/0 > 1, then we'd expect something like a 'Divide by zero error encountered.'. However, running this query against my server yields ten rows, all with '5' in the Jack column.
If we take away the TOP 10, sure enough we get some rows and then get the Divide by zero error. Thus, we can safely conclude that SQL Server is doing early exit evaluation on the CASE statement.
On top of it, the documentation also tells us so:
The CASE statement evaluates its conditions sequentially and stops with the first condition whose condition is satisfied.
Perhaps the question is meant to ask if the common DATEDIFF() subexpression is hoisted from all the CASE statements, computed once, and then evaluated within each predicate's context. By observing the output of SET SHOWPLAN_TEXT ON, I think we can conclude that's not the case:
|--Compute Scalar(DEFINE:([Expr1004]=CASE WHEN datediff(day,CONVERT_IMPLICIT(datetimeoffset(7),[Scratch3].[dbo].[Diffy].[DateOfSale],0),CONVERT_IMPLICIT(datetimeoffset(3),getdate(),0))>(5) THEN '5' ELSE CASE WHEN datediff(day,CONVERT_IMPLICIT(datetimeoffset(7),[Scratch3].[dbo].[Diffy].[DateOfSale],0),CONVERT_IMPLICIT(datetimeoffset(3),getdate(),0))>(10) THEN '10' ELSE CASE WHEN (1)/(0)>(1) THEN 'boom' ELSE '20' END END END))
|--Index Scan(OBJECT:([Scratch3].[dbo].[Diffy].[DiffyHelper]))
From that, we can conclude that the structure of this query means that DATEDIFF() is evaluated for each row and for each predicate, so O(rows * predicates) calls, at worst. That causes some CPU load for the query, but DATEDIFF() isn't quite that expensive and shouldn't be much of a concern. If, in practice, it turns out to be causing a performance problem, there are ways to manually hoist the computation from the query. For example, DATEDIFF() on the date-relative side of the comparison.
Sure, but not in your case (the expression is based on a table column value that changes for each row), but in any event, don't execute the datediff on the table column value, run a dateadd on the predicate (comparison) value so your query can still use any existing index on DateOfSale...
select top 10 *,
case When DateOfSale < dateadd(day, -20, getDate()) then '20'
When DateOfSale < dateadd(day, -15, getDate()) then '15'
When DateOfSale < dateadd(day, -10, getDate()) then '10'
When DateOfSale < dateadd(day, -5, getDate()) then '5'
else '20' end jack
from Foo

Resources