WHERE clause condition checking for NULL - sql

let's say I have a table with columns ID, Date1 and Date2 where Date2can be NULL. I now want to have an SQL statement that ignores Date2 if it is NULL.
So I need something like that:
SELECT *
FROM
[myTable]
WHERE
ID = #someId
AND Date1 <= GETDATE()
AND Date2 >= GETDATE() IF Date2 IS NOT NULL
So I want to check if Date2 is not NULL and then compare it with the current date. If it is NULL then I just want to ignore it.
Hope my request is clear and understandable.
Cheers
Simon

AND Date1 <= GETDATE()
AND (Date2 IS NULL OR Date2 >= GETDATE() )
or
AND Date1 <= GETDATE()
AND COALESCE(Date2, GETDATE()) >= GETDATE()-- which means : if Date2 IS NULL say Date2 = GETDATE()

AND (Date2 >= GETDATE() OR Date2 IS NULL)

You could do it this way:
ISNULL(Date2, GETDATE()) >= GETDATE()

Give this sql a try.
SELECT *
FROM yourtable
WHERE ID = #someId
AND Date1 <= GETDATE()
AND (Date2 IS NULL
AND Date2 >= GETDATE());

SELECT *
FROM
[myTable]
WHERE
ID = #someId
AND Date1 <= GETDATE()
AND Date2 NOT IS NULL
AND Date2 >= GETDATE();

Related

how to deal withenddate null value when you do DATEADD(dd,1, s.endDate))

I have startDate and endDate but I find problem some endDate has null value when I do get value between startDate and endDate +1 I get 0 value because of endDate is null
Select* form s where AND (GETDATE() >= s.startDate AND GETDATE() <= DATEADD(dd,1, s.endDate))
the DATEADD will return null because endDate is null.just I want to ask when I search for range hoe cvan I deal the endDate has null value ?
Try this
Select* form s where AND (GETDATE() >= s.startDate AND
GETDATE() <= DATEADD(dd,1, COALESCE(s.endDate,s.startDate))
DECLARE #nowStart DATETIME = GETDATE();
DECLARE #nowEnd DATETIME = DATEADD(dd, -1, #nowStart)
Select *
from s
where (#nowStart >= s.startDate
and (s.endDate is null or #nowEnd <= s.endDate))

Filtering multiple dates in row with optional to and from parameters

I have a table with three dates:
id date1 date2 date3
1 1945-12-13 1930-11-04 null
2 1970-09-12 1971-09-13 1972-09-14
3 null null null
4 2000-01-01 2001-01-01 2002-01-01
My proc passes in 2 parameters:
#dateFrom datetime = NULL,
#dateTo datetime = NULL
I want to return records that have any date in between the two. NULL for either #dateFrom or #DateTo makes it open ended.
This works for the open ended case, but not for the case where both are not null.
SELECT *
FROM Table1
WHERE (#dateFrom IS NULL
OR ISNULL(date1,'12/31/1753') >= #dateFrom
OR ISNULL(date2,'12/31/1753') >= #dateFrom
OR ISNULL(date3,'12/31/1753') >= #dateFrom)
AND (#dateTo IS NULL
OR ISNULL(date1,'12/31/2099') <= #dateTo
OR ISNULL(date2,'12/31/2099') <= #dateTo
OR ISNULL(date3,'12/31/2099') <= #dateTo)
If I pass #dateFrom = '1940-01-01' and #dateTo = '1950-01-01',
I only want the first record, but I'm getting 1,2,and 4 because they all have dates > 1940.
I just can't wrap my head around how to structure this.
Column and Table names have been changed to protect the innocent.
You need to filter each date field individually within the range, like so:
WHERE
(Date1 >= ISNULL(#DateFrom,'17531231')
AND Date1 <= ISNULL(#dateTo,'20991231'))
OR
(Date2 >= ISNULL(#DateFrom,'1753-12-31')
AND Date2 <= ISNULL(#dateTo,'20991231'))
OR
(Date3 >= ISNULL(#DateFrom,'1753-12-31')
AND Date3 <= ISNULL(#dateTo,'20991231'))
Otherwise you aren't checking the range for each date field, just that a date in that row matches one of the criteria.
Just for another way to look at it. This solution would also work. It makes the where clause simpler at the expense of an additional block of code and a join.
CREATE TABLE #dates (id INT, date1 DATE, date2 DATE, date3 DATE)
INSERT INTO #dates
VALUES
('1','12/13/1945','11/4/1930',NULL),
('2','9/12/1970','9/13/1971','9/14/1972'),
('3',NULL,NULL,NULL),
('4','1/1/2000','1/1/2001','1/1/2002')
DECLARE
#dateFrom datetime = '1940-01-01',
#dateTo datetime = '1950-01-01'
;WITH dateFilter AS (
SELECT id,[Date],DateIndex
FROM
(SELECT
id, date1, date2, date3
FROM #dates) p
UNPIVOT([DATE] FOR DateIndex IN ([date1],[date2],[date3])) AS up
WHERE
up.[DATE] BETWEEN #dateFrom AND #dateTo
)
SELECT
d.*
FROM #dates d
INNER JOIN dateFilter df
ON df.id = d.id
DROP TABLE #dates
Ok this is simplistic but it would work I think since it is in a proc...
declare #startDate datetimne
declare #enddate datetime
if #datefrom is NULL
set #startDate = '12/31/1753'
else
set #startDate = #datefrom
if #dateTo is NULL
set #endDate = '12/31/2099'
else
set #endDate = #dateto
and use #datefrom and #dateto to qualify...

choose minimum date from a record out of multiple columns

Hi I have the following table struct:
Person Date1 Date2............Daten
------ ----- ----- -----
1 2001-01-01 2002-01-01
2 2003-01-01 2000-01-01
and i want to choose the minimum Date between Date1 and Date(n) (20 dates in my case). So for example it would choose Date1 for Person1 and Date2 for Person2.
obviously i can just use min(Date) if I only have 1 date columns, but I can't get my logic right in this case.
Thanks very much.
SELECT person AS the_person
, LEAST(date1 ,date2, date3, date4, date5, ..., dateN ) AS the_date
FROM the_table ;
Least() should ignore NULLs, if present. (the above works for Postgres)
UPDATE (thanks to #WarrenT) apparently DB2 does not have LEAST(), but it does have MIN() instead (having more than one argument).
SELECT person AS the_person
, MIN(date1 ,date2, date3, date4, date5, ..., dateN ) AS the_date
FROM the_table ;
Without commenting on the really bad schema (it violates on of normal form rules - I think it's called no repeating groups),
The only way I know is to use case statement
Select case
When Date1 < Date2 And Date1 < date3 and date1 < date4 and ... Then date1
When Date2 < Date1 And Date2 < date3 and date2 < date4 and ... Then date2
When Date3 < Date1 And Date3 < date2 and date3 < date4 and ... Then date3
When Date4 < Date1 And Date4 < date2 and date4 < date3 and ... Then date4
...
End as MinDate
From table
SQL:
Use this function to get least date between maximum of four dates, if you want to find the minimum for two columns just pass null for date3 and date4.
--Use this function to get least date
--SELECT dbo.GetLeastDate('2021-01-19 01:09:28.997', '2021-01-19 01:07:28.997', '2021-01-19 00:02:28.997', '2021-01-19 02:05:28.997') as theDate
--SELECT dbo.GetLeastDate('2021-01-19 01:09:28.997', '2021-01-19 01:07:28.997', '2021-01-19 02:05:28.997', null) as theDate
--SELECT dbo.GetLeastDate('2021-01-19 01:09:28.997', '2021-01-19 01:07:28.997', null, null) as theDate
--SELECT dbo.GetLeastDate('2021-01-19 01:09:28.997', null, null, null) as theDate
CREATE OR ALTER FUNCTION [dbo].[GetLeastDate]
(
#d1 datetime,
#d2 datetime,
#d3 datetime,
#d4 datetime
)
RETURNS datetime
AS
BEGIN
DECLARE #least datetime
IF #d1 is null
and #d2 is null
and #d3 is null
RETURN null
Set #d1 = Isnull(#d1, getDate())
Set #d2 = Isnull(#d2, getDate())
Set #d3 = Isnull(#d3, getDate())
Set #d4 = Isnull(#d4, getDate())
IF #d1 < #d2 and #d1 < #d3 and #d1 < #d4
SET #least = #d1
ELSE IF #d2 < #d1 and #d2 < #d3 and #d2 < #d4
SET #least = #d2
ELSE IF #d3 < #d1 and #d3 < #d2 and #d3 < #d4
SET #least = #d3
ELSE
SET #least = #d4
RETURN #least
END

Update a DateTimes's Time, but not the date

MyTable:
id int
Date1 DateTime
Date2 DateTime
How can I set the time of Date2 to be the same as Date1 without affecting the date of Date2?
Update Date2 with only the difference in days between the two dates.
UPDATE MyTable
SET Date2 = DATEADD(DAY, DATEDIFF(DAY, Date1, Date2), Date1);
This will preserve the date portion of Date2.
UPDATE: This method essentially reconstructs Date2 by using Date1 as a reference and only adding the difference in days between Date1 and Date2 - preserving the TimeStamp from Date1.
This works from sql server 2008+
select cast(cast(date2 as date) as datetime) + cast(date1 as time) newdate2
from (select getdate() date2, cast('2012-01-01 20:00' as datetime) date1) a
SELECT DATEADD(dd, 0, DATEDIFF(dd, 0, #Date2)) + DATEADD(day, -datediff(day, 0, #Date1), #Date1)

Use something like LEAST in T-SQL on a datetime field [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Getting the minimum of two values in sql
Okay what I Have a table with two datetime fields and I want to select the rows where the oldest date is equal to some date variable. I saw the LEAST function used somewhere but I can't use this in T-SQL
I need something like this
SELECT LEAST(date1, date2) as theDate FROM theTable WHERE theDate = '2012-09-24'
but that will work in T-SQL. Also date1 or date2 can sometimes be null so that may be important to know.
The CASE solution others have provided works well for the case (no pun intended) of two values. For future reference, it becomes a bit unweildy for three or more values and you might then want to do something like this:
SELECT (SELECT MIN(mydate)
FROM (VALUES(date1),(date2),(date3)) mylist(mydate)
) AS theDate
FROM theTable
WHERE theDate = '2012-09-24'
There is no such function in T-SQL. Try:
SELECT theDate = CASE WHEN date1 < date2 THEN date1 ELSE date2 END FROM ... ;
To handle NULLs you may want:
SELECT theDate = NULLIF(CASE WHEN date1 < date2 THEN date1 ELSE date2 END, '20301231')
FROM
(
SELECT
date1 = COALESCE(date1, '20301231'),
date2 = COALESCE(date2, '20301231')
FROM ...
) AS x;
Also, you can't reference the alias theDate in the WHERE clause, it doesn't exist yet. You might want to say:
WHERE '20120924' IN (date1, date2);
You could use a case to mimic least, and a subquery so you can refer to the case result in the where clause:
select *
from (
select case
when date1 > date2 or date1 is null then date2
else date1
end as theDate
, *
from TheTable
)
where theDate = '2012-09-24'
While the other answers are indeed valid, here it is in the form of a UDF, which is closer to what you asked for:
CREATE FUNCTION [dbo].[LeastDate] (#d1 datetime, #d2 datetime)
RETURNS datetime
AS
BEGIN
DECLARE #least datetime
IF #d1 is null or #d2 is null
SET #least = null
ELSE IF #d1 < #d2
SET #least = #d1
ELSE
SET #least = #d2
RETURN #least
END
Usage:
SELECT dbo.LeastDate(date1, date2) as theDate
FROM theTable
WHERE dbo.LeastDate(date1, date2) = '2012-09-24'
Or you can use a nested select to do it one time only:
SELECT * FROM (
SELECT dbo.LeastDate(date1, date2) as theDate FROM theTable
) t
WHERE theDate = '2012-09-24'
Note that the choice of calling the function separately in the where clause or using a nested select is the same as it would be for any SQL function, not just this one.