CASE expressions on datetime columns - sql

I'm trying to access a datetime column to find out whether the date is within a week from today, or overdue. Then write a new column's value to say Incoming, Overdue or Fine.
SELECT
CASE next_action_date
WHEN (BETWEEN GETDATE()+7 AND GETDATE()) THEN 'Incoming'
WHEN (< GETDATE()) THEN 'Overdue'
ELSE 'Fine'
END AS condition
FROM
tableName
This is what I've got so far, but as you can probably see by looking, it doesn't work at all:
Msg 156, Level 15, State 1, Line 3
Incorrect syntax near the keyword 'BETWEEN'.

There are two syntaxes of the CASE expression - the so-called simple one that compares a single value against a list of other values, and a searched one with generic boolean conditions. You picked the simple case, but it does not have enough flexibility for what you need; you should switch to the searched syntax, like this:
SELECT
CASE
WHEN next_action_date BETWEEN GETDATE() AND GETDATE()+7 THEN 'Incoming'
WHEN next_action_date < GETDATE() THEN 'Overdue'
ELSE 'Fine'
END AS condition
FROM
tableName

Please try
select CASE
when next_action_date between GETDATE() and GETDATE()+7 then 'Incoming'
when next_action_date < GETDATE() THEN 'Overdue'
else 'fine' end as Condition
from(
select GETDATE()+6 next_action_date
)x

Try this one -
DECLARE #Date DATETIME
SELECT #Date = GETDATE()
SELECT
condition = CASE
WHEN t.next_action_date BETWEEN #Date AND DATEADD(DAY, 7, #Date) THEN 'Incoming'
WHEN t.next_action_date < #Date THEN 'Overdue'
ELSE 'Fine'
END
FROM dbo.tableName t

use DATEADD(Day, 7, GETDATE())

You should uses the other form of the case statement
SELECT
CASE
WHEN (next_action_date BETWEEN GETDATE()+7 AND GETDATE()) THEN 'Incoming'
WHEN (next_action_date < GETDATE()) THEN 'Overdue'
ELSE 'Fine'
END AS condition
FROM
tableName
http://www.devx.com/tips/Tip/15633

Related

Add a date range to SQL query

I have simple SQL Server view that I need to make amends to:
CREATE VIEW [dbo].[ApplicantStat]
AS SELECT ISNULL(CONVERT(VARCHAR(50), NEWID()), '') AS Pkid,
AVG(ApplicationTime) AS 'AvgApplicationTime',
AVG(ResponseTime) AS 'AvgResponseTime',
CAST(ROUND(100.0 * count(case when [IsAccepted] = 1 then 1 end) / count(case when [IsValid] = 1 then 1 end), 0) AS int) AS 'AcceptRate'
FROM [Application]
It works as planned, but I need to add a date range to it. It's not quite as simple as Where > this date and < that date, instead I need to create a range.
Suppose I have a 'CreatedOn' date in my Application table. I want to be able to include all rows from the last full day (yesterday) and work back 30 days (inclusive).
I'm using SQL Server 2014.
Use :
where CreatedOn between cast(getdate()-30 as date) and cast(getdate()-1 as date)
Please notice CAST is used, it is because to get the full day ignoring the time part.
Something like this:
where MyColumn between dateadd(dd, -1, convert(date, getdate())) and dateadd(dd, -30, convert(date, getdate()))
It's a bit beyond the scope of this question, but maybe useful to some. I like this way of creating a table with date range, to use in queries:
USE MyDataBase
DECLARE #StartDate DATE
DECLARE #EndDate DATE
SET #StartDate = '2014-01-01' -- << user input >> --
SET #EndDate = '2036-12-31' -- << user input >> --
IF OBJECT_ID ('TEMPDB..#Date') IS NOT NULL DROP TABLE #Date
IF OBJECT_ID ('TEMPDB..#Date') IS NULL CREATE TABLE #Date (DateOne DATE)
INSERT INTO #Date VALUES (#StartDate)
WHILE #StartDate < #EndDate
BEGIN
INSERT INTO #Date
SELECT DATEADD (DD, 1, #StartDate) AS Date
SET #StartDate = DATEADD (DD, 1, #StartDate)
END
SELECT * FROM #Date
You should be able to just stick a WHERE with a BETWEEN clause on the end.
CREATE VIEW [dbo].[ApplicantStat]
AS SELECT ISNULL(CONVERT(VARCHAR(50), NEWID()), '') AS Pkid,
AVG(ApplicationTime) AS 'AvgApplicationTime',
AVG(ResponseTime) AS 'AvgResponseTime',
CAST(ROUND(100.0 * count(case when [IsAccepted] = 1 then 1 end) / count(case when [IsValid] = 1 then 1 end), 0) AS int) AS 'AcceptRate'
FROM [Application]
WHERE CreatedOn BETWEEN GETDATE()-1 AND GETDATE()-30

SQL replace using SELECT and invalid column

I have a simple table where the date column answer_6 (formatted as varchar(max) either has a valid date or string Now. I wanted to substitute the Now with the current date/time and then calculate the difference. Here is what I did:
select
CASE [answer_6]
WHEN 'Now' THEN CONVERT(varchar, GETDATE())
ELSE answer_6
END as x,
answer_6 from [tDataMult] where DATEDIFF(yy, GETDATE(), [x]) > 5
The system give me invalid column name 'x'. If I remove the DateDiff SELECT statement works fine.
You can't use aliases in the WHERE clause of the same level as it was defined as WHERE clause is evaluated before the SELECT clause. Try the following :
SELECT t.* FROM (<...>) t WHERE DATEDIFF(yy, GETDATE(), [t.x]) > 5
Instead <...> put your query without WHERE clause.
You can't refer to an alias you've just created in a WHERE clause. The easiest way to fix it would just be to turn your original query into a subquery:
SELECT *
FROM
(
select
CASE [answer_6]
WHEN 'Now' THEN CONVERT(varchar, GETDATE())
ELSE answer_6
END as x,
answer_6 from [tDataMult]
) AS qry
WHERE DATEDIFF(yy, GETDATE(), [x]) > 5
Or you could replicate the expression in your WHERE clause:
select
CASE [answer_6]
WHEN 'Now' THEN CONVERT(varchar, GETDATE())
ELSE answer_6
END as x,
answer_6 from [tDataMult]
WHERE DATEDIFF(yy, GETDATE(),
(CASE [answer_6]
WHEN 'Now' THEN CONVERT(varchar, GETDATE())
ELSE answer_6
END)
) > 5
Column X does not exist in tDataMult table because it is an alias.
Replace it with answer_6 in DateDiff function.
However, one of the possible value of answer_6 column is varchar format ('Now').
You need to have valid data format to use DATEDIFF function properly. (for example: 'yyyy-mm-dd').

SQL Dynamic Column Reuse

I have the following SQL statement:
Select
DateAdd(month, 1, DateField) as MyNewDate,
CASE WHEN MyNewDate < GetDate() THEN 0 ELSE 1 END as Expired
End
I would like to reuse the calculation in the DateAdd without reevaluating the DateAdd for the Expired column. In reality the query is a lot more complex than this simple dateAdd.
The error I get is :
Invalid column name 'MyNewDate'.
How can I reuse the dynamic column?
You can't use an alias in the same query.
You need something like this
SELECT MyNewDate, CASE WHEN MyNewDate < GetDate() THEN 0 ELSE 1 END as Expired
FROM
(
Select DateAdd(month, 1, DateField) as MyNewDate...
)
or retype it like
Select
DateAdd(month, 1, DateField) as MyNewDate,
CASE WHEN DateAdd(month, 1, DateField) < GetDate() THEN 0 ELSE 1 END as Expired
End
SELECT MyNewDate,
CASE WHEN MyNewDate < GetDate() THEN 0 ELSE 1 END as Expired
(
Select
DateAdd(month, 1, DateField) as MyNewDate
FROM tab
)

TSQL Check if date of work completion is less than today

In a employee task application i have to find if the employee has finished the task on time or he is working overtime so i put together this to find it's not working
SELECT case when (CAST('2011-1-1' as datetime) < cast('2011-1-2' as datetime)) THEN 'Finished' ELSE 'UnFinished' end
well the dates are hardcoded here because i wanted to test the logic first before going on.
Edit
Sorry i missed the select before the select statement hence the error
Incorrect syntax near the keyword 'case'.
But now i want to know if there are more efficient ways to do above taking into account that compared fields are datetime
If you need TODAY and date of work finished is datetime, then better use this expression:
DECLARE #today DATETIME
SET #today = CONVERT(varchar, GETDATE(), 112)
SELECT
case when WorkFinishedAt_Column < #today THEN 'Finished' ELSE 'UnFinished' end
FROM YourTable
OR
if you have only one value in variable
DECLARE #today DATETIME
SET #today = CONVERT(varchar, GETDATE(), 112)
SELECT
case when #WorkFinishedAt < #today THEN 'Finished' ELSE 'UnFinished' end
You cant use IF ?
if (CAST('2011-1-1' as datetime) < cast('2011-1-2' as datetime))
select 'Finished'
ELSE select 'UnFinished'

How to get date difference between two dates in same year with one date is from an input date not from the year

Well this is my case: I have an input date X (dd-mm-yyyy), and I want to count the number of days between it with the year part is changed into current year and today's date in SQL. I t comes with the following condition, after the year is changed temporarily: (Here's my current idea of the logic)
- If date X is earlier than today, then difference = datediff(X,now), with the X year is current year
- If date X is later than today, then difference = datediff(X,now), with the X year is one year before
Sample case:
1st case: The input date is 6-6-1990. Today (automatically generated) is 22-8-2011. Then the difference will be = datediff(6-6-2011,22-08-2011)
2nd case: The input date is 10-10-1990. Today (automatically generated) is 22-8-2011. Then the difference will be = datediff(10-10-2010,22-08-2011)
Any idea how to do this in SQL (in SQL Server)? Or is there any other more simple alternatives for this problem? I'd also like this to be done in the query and not using a stored procedure or function
Sorry if there's already a similar question, I just don't know the exact keyword for this problem :( if there's a question like this previously, feel free to direct me there.
Thanks in advance
Here is the implementation (if I understood the logic you need correctly):
USE YourDbName
GO
CREATE FUNCTION YearPartDiff (#date datetime)
RETURNS int
AS
BEGIN
DECLARE #dateCurrentYear datetime
SET #dateCurrentYear = DATEADD(year, YEAR(GETDATE()) - YEAR(#date), #date)
DECLARE #result int
IF #dateCurrentYear < GETDATE()
SET #result = ABS(DATEDIFF(day, #dateCurrentYear, GETDATE()))
ELSE
SET #result = ABS(DATEDIFF(day, DATEADD(year, -1, #dateCurrentYear), GETDATE()))
RETURN(#result)
END
GO
And the example of usage:
USE YourDbName
GO
DECLARE #someDate datetime
SET #someDate = '2011-06-06'
SELECT dbo.YearPartDiff(#someDate) /*returns 77*/
SET #someDate = '2010-10-10'
SELECT dbo.YearPartDiff(#someDate) /*returns 316*/
Basically, #Andrei's solution, but in a single statement:
SELECT
DayDiff = DATEDIFF(
DAY,
DATEADD(YEAR, CASE WHEN LastOcc > GETDATE() THEN -1 ELSE 0 END, LastOcc),
GETDATE()
)
FROM (
SELECT LastOcc = DATEADD(YEAR, YEAR(GETDATE()) - YEAR(#InputDate), #InputDate)
) s
This seems to do the job
SELECT DATEDIFF(DAY, CONVERT(DATETIME, N'2011-06-06'), CONVERT(DATETIME, N'2011-08-22'))
So the basic syntax is
SELECT DATEDIFF(DAY, CONVERT(DATETIME, N'yyyy-mm-dd'), CONVERT(DATETIME, N'yyyy-mm-dd '))
Alternatively, you can use GETDATE() instead of the string for today's date
I have used "SELECT DATEDIFF( D, "+myDate+", GETDATE())" in my code, on SQL Server 2005. It works for me. The value myDate of course would be the DateTime input value.
you should try this query:
create table #T (inp_date datetime)
insert #T values ('06-06-1990')
insert #T values ('08-22-1990')
insert #T values ('10-10-1990')
--select * from #T
select inp_date, GETDATE(),
CASE
WHEN DATEADD(yy,DATEDIFF(yy,inp_date,GETDATE()),inp_date) <= GETDATE()
THEN DATEDIFF(dd,DATEADD(yy,DATEDIFF(yy,inp_date,GETDATE()),inp_date),GETDATE())
ELSE DATEDIFF(dd,DATEADD(yy,DATEDIFF(yy,inp_date,GETDATE())-1,inp_date),GETDATE())
END
from #T