Date comparing between two dates? [duplicate] - sql-server

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Value should be 0 between the two dates?
SQL Server 2000
Table1
ID Date Workedtime
001 23-02-2009 08:00:00
001 24-02-2009 15:00:00
001 25-02-2009 17:00:00
002 ...
So on..,
Table2
ID FromDate ToDate
001 24-02-2009 25-02-2009
002 27-02-2009 03-03-2009
...
I want to compare the table1 date and ID with Table2 ID FromDate, ToDate, means
Table1 Date compare with FromDate ToDate, if Date is comes in between fromdate and todate, the worktime should display absent.
Expected Output
ID Date Workedtime
001 23-02-2009 08:00:00
001 24-02-2009 absent
001 25-02-2009 absent
002 ...
Need Query Help

This should help from what you have specified above
DECLARE #Table1 TABLE(
ID VARCHAR(10),
Date DATETIME,
Workedtime VARCHAR(10)
)
INSERT INTO #Table1 (ID,Date,Workedtime) SELECT '001', '23 Feb 2009', '08:00:00'
INSERT INTO #Table1 (ID,Date,Workedtime) SELECT '001', '24 Feb 2009', '15:00:00'
INSERT INTO #Table1 (ID,Date,Workedtime) SELECT '001', '25 Feb 2009', '17:00:00'
DECLARE #Table2 TABLE(
ID VARCHAR(10),
FromDate DATETIME,
ToDate DATETIME
)
INSERT INTO #Table2 (ID,FromDate,ToDate) SELECT '001', '24 Feb 2009', ' 25 Feb 2009'
SELECT t1.ID,
t1.Date,
CASE WHEN t2.ID IS NULL THEN t1.Workedtime ELSE 'absent' END Workedtime
FROM #Table1 t1 LEFT JOIN
#Table2 t2 ON t1.ID = t2.ID
AND t1.Date BETWEEN t2.FromDate AND t2.ToDate

Related

How do i select the free time between start time and end time in sql?

I want to select all the free time other that the mentioned ones for which the room is free.
eg table:
room starttime endtime date
1 | 12pm | 1pm | 2018-02-18 00:00:00.000
1 | 2pm | 3pm | 2018-02-18 00:00:00.000
1 | 3pm | 5pm | 2018-02-18 00:00:00.000
expected output eg:
freetime
6-12,5-10
Is this even possible?
Thanks in advance.
This is for a assignment where the room is booked for a class for particular starttime(date) and endtime(date) and date.
I need to find out the times when the class will be free.
Above free timings was just an example.
Possible solution:
set dateformat ymd
-- Sample data
declare #MyTable
table (room varchar(1), starttime varchar(4), endtime varchar(4), [date] datetime)
insert into #MyTable values ('1', '12pm', '1pm', '2018-02-18 00:00:00.000')
insert into #MyTable values ('1', '2pm', '3pm', '2018-02-18 00:00:00.000')
insert into #MyTable values ('1', '3pm', '5pm', '2018-02-18 00:00:00.000')
select d.[date], r.room, t.freehour
from
(select cast(dateadd(hour, number, 0) as time) as freehour
from master..spt_values where type = 'P' and number between 6 and 22) t,
(select distinct room from #MyTable) r,
(select distinct [date] as [date] from #MyTable) d
where not exists (
select 1
from #MyTable m
where m.[date] = d.[date]
and m.room = r.room
and t.freehour between cast(m.starttime as time)
and dateadd(hour,-1,cast(m.endtime as time))
)

want to show record of same date previous and next time slot for a given date

I have a table with multiple record against userid and datetime fields. A user have availability for same date everyhour.
UserId DateTime
1 2018-08-13 08:30:00 +05:30
1 2018-08-13 09:30:00 +05:30
1 2018-08-13 10:30:00 +05:30
1 2018-08-13 15:00:00 +05:30
1 2018-08-13 17:00:00 +05:30
1 2018-08-13 18:00:00 +05:30
Now If I search for date suppose 2018-08-13 11:30:00 +05:30
then I want in
Previous slot = 2018-08-13 **10:30:00** +05:30
and next slot = 2018-08-13 **15:00:00** +05:30
Update
Quick update I need smaller time for the same date not the previous day. Ex. For
2018-08-13 08:30:00 +05:30 it should show null as no small time available.
One more try with CTEs, edited to match the changed question:
DECLARE #SearchDate datetime = '2018-08-13 11:30:00',
#StartDate datetime,
#EndDate datetime,
#UserId int = 1;
SET #StartDate = DATETIMEFROMPARTS(YEAR(#SearchDate), MONTH(#SearchDate), DAY(#SearchDate), 0, 0, 0, 0);
SET #EndDate = DATEADD(day, 1, #StartDate);
WITH
ctePrevious AS
(
SELECT MAX([DateTime]) AS [DateTime]
FROM YourTable
WHERE UserId = #UserId AND [DateTime] BETWEEN #StartDate AND #SearchDate
),
cteNext AS
(
SELECT MIN([DateTime]) AS [DateTime]
FROM YourTable
WHERE UserId = #UserId AND [DateTime] BETWEEN #SearchDate AND #EndDate
)
SELECT ctePrevious.[DateTime] AS prevDate, cteNext.[DateTime] AS nextDate
FROM ctePrevious, cteNext
It should return NULL values if no entry is found for the given date.
You could add a rownumber and a self join. The following example will demonstrate how it works:
CREATE TABLE #T (ID INT, DateT DATETIME)
INSERT INTO #T VALUES (1, GETDATE() - .2)
INSERT INTO #T VALUES (1, GETDATE() - .1)
INSERT INTO #T VALUES (1, GETDATE() - .05)
INSERT INTO #T VALUES (1, GETDATE())
INSERT INTO #T VALUES (1, GETDATE() + .1);
WITH CTE AS
(
SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS RowNumb
FROM #T AS T
)
SELECT C.ID, C.DateT AS StartDate, C2.DateT AS EndDate
FROM CTE AS C
LEFT JOIN CTE AS C2 ON C.RowNumb = C2.RowNumb - 1
WHERE GETDATE() BETWEEN C.DateT AND C2.DateT -- your date input here
Make use of LEAD and LAG. This is Pseudo SQL, however:
SELECT DateColumn,
LAG(DateColumn) OVER (ORDER BY DateColumn) AS Previousslot,
LEAD(DateColumn) OVER (ORDER BY DateColumn) AS NextSlot
FROM YourTable;
This, unlike SQL_M's answer, means you don't need to do 2/3 scans of the table.
declare #wantedDate datetime = '2018-09-04 12:27:16.570'
select top 1 * from #t tP -- Top of each min and max time
join #T tn
on tp.ID = tn.ID
and tp.DateT <= #wantedDate -- all previous times
and tn.DateT >= #wantedDate -- all next times
order by tp.ID, tp.DateT desc, tn.DateT
Revert me, if query needs updates.

How to find missing dates by ID

I need help modifying a script to find the missing RevenuePeriod by ID within a given time frame. I have found a similar script that finds the missing date for a given ID but I don't know how to modify the script where it will give the missing dates per ID.
create table #WorksheetHistory (WorksheetID [int] IDENTITY(1,1) ,ID varchar(6), RevenuePeriod datetime)
insert into #WorksheetHistory (ID,RevenuePeriod)
SELECT '000001','2015-06-01 00:00:00.00' Union All
SELECT '000001','2015-07-01 00:00:00.00' Union All
SELECT '000001','2015-11-01 00:00:00.00' Union All
SELECT '000001','2015-12-01 00:00:00.00' Union All
SELECT '000002','2015-06-01 00:00:00.00' Union All
SELECT '000002','2015-12-01 00:00:00.00'
DECLARE #EndDate datetime
DECLARE #StartDate datetime
SET #StartDate = '2015-06-01 00:00:00.00'
SET #EndDate = '2015-12-01 00:00:00.00'
;WITH Dates as
(
SELECT #StartDate AS dt
UNION ALL
SELECT DATEADD(month, 1, dt) as dt
FROM Dates
WHERE dt < (select dateadd(month,-1,#EndDate) enddate)
)
select Month(dt) as dtMonth, Year(dt) dtYear
from Dates d left outer join #WorksheetHistory w
on dateadd(month, datediff(month,0,d.dt),0) = dateadd(month, datediff(month,0,w.RevenuePeriod),0) Where RevenuePeriod is null
Drop Table #WorksheetHistory
The current output returns the following output. I realize in the script it doesnt have an ID returned, but even if I do, it would return null value as the script indicates return null dates. I don't know how to put the associated ID in it too.
dt
2015-08-01 00:00:00.000
2015-09-01 00:00:00.000
2015-10-01 00:00:00.000
My desired result would be return the Missing ID's with the respective missing dates.
ID dt
000001 2015-08-01 00:00:00.00
000001 2015-09-01 00:00:00.00
000001 2015-10-01 00:00:00.00
000002 2015-07-01 00:00:00.00
000002 2015-08-01 00:00:00.00
000002 2015-09-01 00:00:00.00
000002 2015-10-01 00:00:00.00
000002 2015-11-01 00:00:00.00
Use EXCEPT:
WITH Dates as
(
SELECT #StartDate AS dt
UNION ALL
SELECT DATEADD(month, 1, dt) as dt
FROM Dates
WHERE dt < DATEADD(m, -1, #EndDate)
)
-- all the possible combinations
SELECT w.ID, d.dt
FROM Dates d
CROSS JOIN (
SELECT ID
FROM #WorksheetHistory
GROUP BY ID
) w
EXCEPT
-- the combinations you actually have
SELECT w.ID, d.dt
FROM Dates d
JOIN #WorksheetHistory w
ON d.dt = w.RevenuePeriod;

JOIN on multilple rows to SELECT only TOP row in SQL Sever

I have a table which has only 1 row per ID/Date while the other one can have overlapping ID/Dates. I need to JOIN them in such a way that only top row is selected (actually any row from duplicates table is fine!). Its fairly easy to do this in 2 steps (Insert & Update) but I'm looking if it can be done in a single step.
CREATE TABLE #Row1Each (ID VARCHAR(10), Date_ DATETIME, Value FLOAT) INSERT INTO #Row1Each SELECT 'AAPL', '1/10/2015', 100 INSERT INTO #Row1Each SELECT 'MSFT', '1/10/2015', 20
CREATE TABLE #Table1 (ID VARCHAR(10), Date_ DATETIME, Qty FLOAT) INSERT INTO #Table1 SELECT 'AAPL', '1/10/2015', 55000
CREATE TABLE #Duplicates (ID VARCHAR(10), StartDate DATETIME, EndDate DATETIME, Quote FLOAT) INSERT INTO #Duplicates SELECT 'AAPL', '1/2/2015', '12/31/2016', 0.1 INSERT INTO #Duplicates SELECT 'AAPL', '1/4/2015', '10/05/2016', 0.11
/*
AAPL 2015-01-10 00:00:00.000 100
MSFT 2015-01-10 00:00:00.000 20
AAPL 2015-01-10 00:00:00.000 55000
AAPL 2015-01-02 00:00:00.000 2016-12-31 00:00:00.000 0.1
AAPL 2015-01-04 00:00:00.000 2016-10-05 00:00:00.000 0.1
*/
SELECT A.*
, B.Qty
, C.Quote
FROM #Row1Each A
LEFT JOIN #Table1 B ON B.ID = A.ID
AND B.Date_ = A.Date_
LEFT JOIN #Duplicates C ON C.ID = A.ID
AND A.Date_ BETWEEN C.StartDate AND C.EndDate
DROP TABLE #Row1Each DROP TABLE #Table1 DROP TABLE #Duplicates
/* Desired output
AAPL 2015-01-10 00:00:00.000 100 55000 0.1
MSFT 2015-01-10 00:00:00.000 20 NULL NULL
*/
You can do this using APPLY.
SELECT
r.Id,
r.Date_,
r.Value,
t.Qty,
d.Quote
FROM #Row1Each r
LEFT JOIN #Table1 t
ON t.ID = r.ID
AND t.Date_ = r.Date_
OUTER APPLY(
SELECT TOP 1 *
FROM #Duplicates d
WHERE
d.ID = r.ID
AND r.Date_ BETWEEN d.StartDate AND d.EndDate
ORDER BY EndDate DESC -- Returns Top 1 Based on EndDate
)d

comparing with dates?

Using SQL Server 2000
Table1
ID Name, Date, TimeIn, TimeOut, DateIn, Dateout
AEAA00294 Alexander 13/10/2008 09:00:00 18:00:00 13/10/2008 13/10/2008
AEAA00294 Alexander 14/10/2008 16:00:00 02:00:00 14/10/2008 15/10/2008
AEAA00294 Alexander 16/10/2008 09:00:00 18:00:00 16/10/2008 16/10/2008
So on…,
Table2
ID Date
DATE, TIME, ID
20081013 103417 AEAA00294
20081013 151552 AEAA00294
20081013 170836 AEAA00294
20081013 170909 AEAA00294
20081013 171015 AEAA00294
20081014 163648 AEAA00294
20081014 030838 AEAA00294
20081015 144708 AEAA00294
20081015 151133 AEAA00294
20081016 095211 AEAA00294
So on…,
From the above two table I am taking Intime that is min (time) as Intime on the date and max (time) as Outtime on the same date from table2 where table1.personid = table2.personid.
In table1 DateIn and Dateout Date is same, it should take min (time) and Max (time) on the same date from the table2
Suppose table1 DateIn and Dateout Date is different, it should take min (time) and Max (time) from table2 compare with table1.dateIn and table2.Dateout
Expected Output
ID Date Intime Outtime
AEAA00294 20081013 103417 171015
AEAA00294 20081014 030838 151133
So on…,
My Query
SELECT DISTINCT DERIVEDTBL.PERSONID, DERIVEDTBL.CARDEVENTDATE, MIN(DERIVEDTBL.CARDEVENTTIME) AS INTIME, MAX(DERIVEDTBL.CARDEVENTTIME) AS OUTTIME, tmp_Cardevent1.Normal_Intime, tmp_Cardevent1.Normal_Outtime, tmp_Cardevent1.CardEventDate AS Expr1, tmp_Cardevent1.DateIn, tmp_Cardevent1.DateOut FROM (SELECT T_PERSON.PERSONID, T_CARDEVENT.CARDEVENTDATE, CONVERT(VARCHAR(10), SUBSTRING(T_CARDEVENT.CARDEVENTTIME, 1, 2) + ':' + SUBSTRING(T_CARDEVENT.CARDEVENTTIME, 3, 2) + ':' + SUBSTRING(T_CARDEVENT.CARDEVENTTIME, 5, 2), 8) AS CARDEVENTTIME
FROM T_CARDEVENT LEFT JOIN T_PERSON ON T_CARDEVENT.PERSONID = T_PERSON.PERSONID) DERIVEDTBL INNER JOIN tmp_Cardevent1 ON DERIVEDTBL.PERSONID = tmp_Cardevent1.PERSONID AND DERIVEDTBL.CARDEVENTDATE = tmp_Cardevent1.CardEventDate GROUP BY DERIVEDTBL.CARDEVENTDATE, DERIVEDTBL.PERSONID, tmp_Cardevent1.Normal_Intime, tmp_Cardevent1.Normal_Outtime, tmp_Cardevent1.CardEventDate, tmp_Cardevent1.DateIn, tmp_Cardevent1.DateOut
Table1 as tmp_cardevent1 and Table2 as Derivedtbl in my query.
From the above i want to compare derivedtbl date with tmp_cardevent1 dateIn and DateOut values.
Need Query Help.
How to make a query for this condition?
Try something like this
DECLARE #Table1 TABLE(
ID VARCHAR(50),
PNAME VARCHAR(50),
Date DATETIME,
TimeIN VARCHAR(10),
[TimeOut] VARCHAR(10),
DateIn DATETIME,
DateOut DATETIME
)
INSERT INTO #Table1 (ID,PNAME,Date,TimeIN,[TimeOut],DateIn,DateOut)
SELECT 'AEAA00294','Alexander','13 Oct 2008', '09:00:00', '18:00:00','13 Oct 2008','13 Oct 2008'
INSERT INTO #Table1 (ID,PNAME,Date,TimeIN,[TimeOut],DateIn,DateOut)
SELECT 'AEAA00294','Alexander','14 Oct 2008', '16:00:00', '02:00:00','14 Oct 2008','15 Oct 2008'
INSERT INTO #Table1 (ID,PNAME,Date,TimeIN,[TimeOut],DateIn,DateOut)
SELECT 'AEAA00294','Alexander','16 Oct 2008', '09:00:00', '18:00:00','16 Oct 2008','16 Oct 2008'
DECLARE #Table2 TABLE(
Date DATETIME,
[Time] VARCHAR(10),
ID VARCHAR(50)
)
INSERT INTO #Table2 (Date,[Time],ID) SELECT '13 Oct 2008', '10:34:17', 'AEAA00294'
INSERT INTO #Table2 (Date,[Time],ID) SELECT '13 Oct 2008' , '15:15:52' , 'AEAA00294'
INSERT INTO #Table2 (Date,[Time],ID) SELECT '13 Oct 2008' , '17:08:36' , 'AEAA00294'
INSERT INTO #Table2 (Date,[Time],ID) SELECT '13 Oct 2008' , '17:09:09' , 'AEAA00294'
INSERT INTO #Table2 (Date,[Time],ID) SELECT '13 Oct 2008' , '17:10:15' , 'AEAA00294'
INSERT INTO #Table2 (Date,[Time],ID) SELECT '14 Oct 2008' , '16:36:48' , 'AEAA00294'
INSERT INTO #Table2 (Date,[Time],ID) SELECT '14 Oct 2008' , '03:08:38' , 'AEAA00294'
INSERT INTO #Table2 (Date,[Time],ID) SELECT '15 Oct 2008' , '14:47:08' , 'AEAA00294'
INSERT INTO #Table2 (Date,[Time],ID) SELECT '15 Oct 2008' , '15:11:33' , 'AEAA00294'
INSERT INTO #Table2 (Date,[Time],ID) SELECT '16 Oct 2008' , '09:52:11' , 'AEAA00294'
SELECT t1.ID,
t1.PNAME,
t1.DateIn,
t1.DateOut,
MIN(CAST(t2In.[Time] AS DATETIME)),
MAX(CAST(t2Out.[Time] AS DATETIME))
FROM #Table1 t1 LEFT JOIN
#Table2 t2IN ON t1.ID = t2IN.ID
AND t1.DateIn = t2IN.Date LEFT JOIN
#Table2 t2Out ON t1.ID = t2Out.ID
AND t1.DateOut = t2Out.Date
GROUP BY t1.ID,
t1.PNAME,
t1.DateIn,
t1.DateOut
I think this will do it:
update table1 set timein=t2.timein, timeout=t2.timeout from table1 t1 join
(select ID, date, min(time) as timein, max(time) as timeout from table2 group by is, date) as t2 on t1.id=t2.id

Resources