comparing with dates? - sql-server

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

Related

Substract date from previous row by group SQL query

Data
id date
2380 10/30/12 09:00:00
2380 10/30/12 09:05:00
2380 10/30/12 09:10:00
2380 10/30/12 09:15:00
2381 10/30/12 10:00:00
2381 10/30/12 10:05:00
2381 10/30/12 10:10:00
2381 10/30/12 10:15:00
2382 10/30/12 11:00:00
2382 10/30/12 11:05:00
2382 10/30/12 10:10:00
2382 10/30/12 10:15:00
and I want the following solution
id date duration
2380 10/30/12 09:00:00 00:00:00
2380 10/30/12 09:05:00 00:05:00
2380 10/30/12 09:10:00 00:10:00
2380 10/30/12 09:15:00 00:15:00
2381 10/30/12 10:00:00 00:00:00
2381 10/30/12 10:05:00 00:05:00
2381 10/30/12 10:10:00 00:10:00
2381 10/30/12 10:15:00 00:15:00
2382 10/30/12 11:00:00 00:00:00
2382 10/30/12 11:05:00 00:05:00
2382 10/30/12 10:10:00 00:10:00
2382 10/30/12 10:15:00 00:10:00
I have tried to understand the logic behind the following thread but it's difficult to understand.
Substract date from previous row by group (using R)
select id, date, date - (select min(date) from date group by id) as duration
from date
Closest I have got is for one id.
Try this below example hope this is what you are looking as output,
declare #t1 table
(
id int,
dtdate datetime
)
insert into #t1 values(2380,'10/30/12 09:00:00')
insert into #t1 values(2380,'10/30/12 09:05:00')
insert into #t1 values(2380,'10/30/12 09:10:00')
insert into #t1 values(2380,'10/30/12 09:15:00')
insert into #t1 values(2381,'10/30/12 10:00:00')
insert into #t1 values(2381,'10/30/12 10:05:00')
insert into #t1 values(2381,'10/30/12 10:10:00')
insert into #t1 values(2381,'10/30/12 10:15:00')
insert into #t1 values(2382,'10/30/12 11:00:00')
insert into #t1 values(2382,'10/30/12 11:05:00')
insert into #t1 values(2382,'10/30/12 10:10:00')
insert into #t1 values(2382,'10/30/12 10:15:00')
;WITH CTE AS (
SELECT
rownum = ROW_NUMBER() OVER (partition by id ORDER BY id,dtDate),
id,dtDate
FROM #t1 p
)
SELECT
a.id,
a.dtDate,
CASE WHEN prev.dtdate is NULL THEN '00:00:00' ELSE convert(nvarchar(8),a.dtdate- prev.dtdate,108) END as duration
FROM CTE a
LEFT JOIN CTE prev ON a.id = prev.id AND prev.rownum = a.rownum - 1
The key to my approach is to find the minimum date value for each id which I refer to as the ReferenceDate. Then I join the main table to that and do the date math with the DATEDIFF() function and transform the results to hh:mi:ss with the CONVERT() function using style 108. Here is the dbfiddle.
IF OBJECT_ID('tempdb.dbo.#MyTable', 'U') IS NOT NULL
DROP TABLE #MyTable;
CREATE TABLE #MyTable
(
id INTEGER NOT NULL
, date DATETIME NOT NULL
);
INSERT INTO #MyTable (id, date) VALUES (2380, '10/30/12 09:00:00');
INSERT INTO #MyTable (id, date) VALUES (2380, '10/30/12 09:05:00');
INSERT INTO #MyTable (id, date) VALUES (2380, '10/30/12 09:10:00');
INSERT INTO #MyTable (id, date) VALUES (2380, '10/30/12 09:15:00');
INSERT INTO #MyTable (id, date) VALUES (2381, '10/30/12 10:00:00');
INSERT INTO #MyTable (id, date) VALUES (2381, '10/30/12 10:05:00');
INSERT INTO #MyTable (id, date) VALUES (2381, '10/30/12 10:10:00');
INSERT INTO #MyTable (id, date) VALUES (2381, '10/30/12 10:15:00');
INSERT INTO #MyTable (id, date) VALUES (2382, '10/30/12 11:00:00');
INSERT INTO #MyTable (id, date) VALUES (2382, '10/30/12 11:05:00');
INSERT INTO #MyTable (id, date) VALUES (2382, '10/30/12 10:10:00');
INSERT INTO #MyTable (id, date) VALUES (2382, '10/30/12 10:15:00');
INSERT INTO #MyTable (id, date) VALUES (2382, '10/30/12 12:15:00');
INSERT INTO #MyTable (id, date) VALUES (2382, '10/30/12 10:15:30');
SELECT a.*
, CONVERT(NVARCHAR(8), a.date - b.ReferenceDate, 108) AS duration
FROM #MyTable AS a
INNER JOIN (
SELECT id, MIN(date) AS ReferenceDate
FROM #MyTable GROUP BY id) AS b ON a.id = b.id;

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 can I group rows by DateTime if the values are almost the same?

How can I group rows if the different time between on field and other field in other row almost the same?
For example:
GUID - No - sDateTime - eDateTime - Name
------------------------------------------------------------------
0000 - 01 - 2013-02-02 08:00:00 - 2013-02-02 08:40:00 - A
0000 - 02 - 2013-02-02 08:45:00 - 2013-02-02 09:45:00 - A
0000 - 03 - 2013-02-02 11:30:00 - 2013-02-02 12:00:00 - A
0000 - 04 - 2013-02-02 09:55:00 - 2013-02-02 11:00:00 - A
0000 - 05 - 2013-02-02 11:05:00 - 2013-02-02 12:30:00 - B
How can I get sDateTime from row with eDateTime from other row if the different not more than 10 minutes?
GUID - No - SDateTime - EDateTime (From other row) - Name
----------------------------------------------------------------------------
0000 -01,02,04 - 2013-02-02 08:00:00 - **2013-02-02 11:00:00** - A
0000 - 03 - 2013-02-02 11:30:00 - 2013-02-02 12:00:00 - A
0000 - 05 - 2013-02-02 11:05:00 - 2013-02-02 12:30:00 - B
No cursors here but this is still a loop over rows using a recursive CTE to figure out what rows should be grouped together. The temp table #T is there to hold the ID that connects rows to each other. It could have been done without the temp table but for performance reasons it is better to do it with a temp table instead of having another CTE as the source for the recursive CTE.
In the final query I use the for xml path trick to concatenate the values from No. That means that the CTE C is used a second time so it will be executed twice. You might want to turn that CTE to a temp table as well to avoid that.
SQL Fiddle
MS SQL Server 2008 Schema Setup:
create table YourTable
(
GUID varchar(4),
No varchar(2),
sDateTime datetime,
eDateTime datetime,
Name varchar(1)
);
insert into YourTable values
('0000', '01', '2013-02-02 08:00:00', '2013-02-02 08:40:00', 'A'),
('0000', '02', '2013-02-02 08:45:00', '2013-02-02 09:45:00', 'A'),
('0000', '03', '2013-02-02 11:30:00', '2013-02-02 12:00:00', 'A'),
('0000', '04', '2013-02-02 09:55:00', '2013-02-02 11:00:00', 'A'),
('0000', '05', '2013-02-02 11:05:00', '2013-02-02 12:30:00', 'B');
Query 1:
create table #T
(
ID int,
GUID varchar(4),
No varchar(2),
sDateTime datetime,
eDateTime datetime,
Name varchar(1),
primary key(ID, GUID, Name)
);
insert into #T(ID, GUID, No, sDateTime, eDateTime, Name)
select row_number() over(partition by GUID, Name order by sDateTime),
GUID, No, sDateTime, eDateTime, Name
from YourTable;
with C as
(
select T.ID, T.GUID, T.No, T.sDateTime, T.eDateTime, T.Name, 1 as Grp
from #T as T
where T.ID = 1
union all
select T.ID, T.GUID, T.No, T.sDateTime, T.eDateTime, T.Name,
C.Grp + case when datediff(minute, C.eDateTime, T.sDateTime) > 10
then 1
else 0
end
from #T as T
inner join C
on T.ID = C.ID + 1 and
T.Name = C.Name and
T.GUID = C.GUID
)
select C.GUID,
(
select ','+C2.No
from C as C2
where C.GUID = C2.GUID and
C.Name = C2.Name and
C.Grp = C2.Grp
order by C2.No
for xml path(''), type
).value('substring(text()[1], 2)', 'varchar(max)') as No,
min(C.sDateTime) as sDateTime,
max(C.eDateTime) as eDateTime,
C.Name
from C
group by C.GUID, C.Name, C.Grp
drop table #T;
Results:
| GUID | NO | SDATETIME | EDATETIME | NAME |
----------------------------------------------------------------------------------------------
| 0000 | 01,02,04 | February, 02 2013 08:00:00+0000 | February, 02 2013 11:00:00+0000 | A |
| 0000 | 03 | February, 02 2013 11:30:00+0000 | February, 02 2013 12:00:00+0000 | A |
| 0000 | 05 | February, 02 2013 11:05:00+0000 | February, 02 2013 12:30:00+0000 | B |
Just for fun, a SQL Server 2012 version.
with CMinDiff as
(
select GUID, No, sDateTime, eDateTime, Name,
case when datediff(minute,
coalesce(lag(eDateTime) over(partition by GUID, Name
order by eDateTime),
sDateTime),
sDateTime) <= 10
then 0
else 1
end as MinDiff
from YourTable
), CSumMinDiff as
(
select GUID, No, sDateTime, eDateTime, Name,
sum(MinDiff) over(partition by GUID, Name
order by sDateTime
rows between unbounded preceding and current row) as Grp
from CMinDiff
)
select C.GUID,
(
select ','+C2.No
from CSumMinDiff as C2
where C.GUID = C2.GUID and
C.Name = C2.Name and
C.Grp = C2.Grp
order by C2.No
for xml path(''), type
).value('substring(text()[1], 2)', 'varchar(max)') as No,
min(C.sDateTime) as sDateTime,
max(C.eDateTime) as eDateTime,
C.Name
from CSumMinDiff as C
group by C.GUID, C.Name, C.Grp
I was unable to perform this without a cursor, maybe somebody smarter can come up with a solution that does not include cursors, but this is what I have:
CREATE TABLE MyTable
(
[GUID] VARCHAR(4),
[No] VARCHAR(2),
[sDateTime] DATETIME,
[eDateTime] DATETIME,
[Name] VARCHAR(1)
)
INSERT INTO [MyTable]
([GUID], [No], [sDateTime], [eDateTime], [Name])
VALUES
('0000', '01', '2013-02-02 08:00:00', '2013-02-02 08:40:00', 'A'),
('0000', '02', '2013-02-02 08:45:00', '2013-02-02 09:45:00', 'A'),
('0000', '03', '2013-02-02 11:30:00', '2013-02-02 12:00:00', 'A'),
('0000', '04', '2013-02-02 09:55:00', '2013-02-02 11:00:00', 'A'),
('0000', '05', '2013-02-02 11:05:00', '2013-02-02 12:30:00', 'B')
DECLARE #MyTable TABLE
(
[GUID] VARCHAR(4),
[No] VARCHAR(100),
[sDateTime] DATETIME,
[eDateTime] VARCHAR(100),
[Name] VARCHAR(1)
)
DECLARE [MyCursor] CURSOR FOR
SELECT [GUID], [No], [sDateTime], [eDateTime], [Name]
FROM [MyTable]
ORDER BY [Name], [sDateTime];
DECLARE #GUID AS VARCHAR(4)
DECLARE #No AS VARCHAR(2)
DECLARE #sDateTime AS DATETIME
DECLARE #eDateTime AS DATETIME
DECLARE #Name AS VARCHAR(1)
DECLARE #OldName AS VARCHAR(1)
SET #OldName = ''
DECLARE #MergedNo AS VARCHAR(100)
SET #MergedNo = NULL
DECLARE #sOldDateTime AS DATETIME
DECLARE #eOldDateTime AS DATETIME
OPEN [MyCursor]
FETCH NEXT FROM [MyCursor]
INTO #GUID, #No, #sDateTime, #eDateTime, #Name
WHILE ##FETCH_STATUS = 0
BEGIN
IF (#OldName = '')
BEGIN
SET #sOldDateTime = #sDateTime
SET #OldName = #Name
END
ELSE IF (#OldName <> #Name OR DATEDIFF(MINUTE, #eOldDateTime, #sDateTime) > 10)
BEGIN
INSERT INTO #MyTable
([GUID], [No], [sDateTime], [eDateTime], [Name])
VALUES
(#GUID, #MergedNo, #sOldDateTime, CASE WHEN #MergedNo LIKE '%,%' THEN '**' + CONVERT(VARCHAR(100), #eOldDateTime, 20) + '**' ELSE CONVERT(VARCHAR(100), #eOldDateTime, 20) END, #Name)
SET #sOldDateTime = #sDateTime
SET #OldName = #Name
SET #MergedNo = NULL
END
SET #MergedNo = COALESCE(#MergedNo + ', ', '') + #No
SET #eOldDateTime = #eDateTime
FETCH NEXT FROM [MyCursor]
INTO #GUID, #No, #sDateTime, #eDateTime, #Name
END
CLOSE [MyCursor];
DEALLOCATE [MyCursor];
IF (#OldName <> '')
BEGIN
INSERT INTO #MyTable
([GUID], [No], [sDateTime], [eDateTime], [Name])
VALUES
(#GUID, #MergedNo, #sOldDateTime, CASE WHEN #MergedNo LIKE '%,%' THEN '**' + CONVERT(VARCHAR(100), #eOldDateTime, 20) + '**' ELSE CONVERT(VARCHAR(100), #eOldDateTime, 20) END, #Name)
END
SELECT *
FROM #MyTable
DROP TABLE [MyTable]

Sql Server transform a select row into multiple rows base on time values

Please look the following query:
SELECT ID, START, END FROM TABLEA
the result is:
ID START END
1 2012-06-07 19:32:00 2012-06-08 06:00:00
2 2012-06-08 06:00:00 NULL
But I want really a result like this:
START END
2012-06-07 19:32:00 2012-06-07 23:59:59
2012-06-08 00:00:00 NULL
The id no matters.
And look at this example:
ID START END
1 2012-06-06 19:32:00 2012-06-08 06:00:00
2 2012-06-08 06:00:00 NULL
It Must be:
START END
2012-06-06 19:32:00 2012-06-06 23:59:59
2012-06-07 00:00:00 2012-06-07 23:59:59
2012-06-08 00:00:00 NULL
The idea is to generate rows with the start and end values within the same day.
Thanks in advance.
The following solution does everything you want, all in SQL. It merges overlapping and contiguous timespans (including wholly-overlapping timespans) and also breaks out multi-day timespans by date using a calendar table.
declare #TimeSheetEntries table
(
ID int identity not null primary key,
[Start] datetime not null,
[End] datetime null
);
declare #CalendarTable table
(
CalDate datetime
)
DECLARE #CurDate datetime = '2000-01-01 00:00:00';
WHILE #CurDate <= '2020-12-31'
BEGIN
INSERT INTO #CalendarTable
SELECT #CurDate;
SELECT #CurDate = DATEADD(day,1,#CurDate);
END
insert into #TimeSheetEntries
(
[Start],
[End]
)
select
'2012-06-06 19:32:00',
'2012-06-08 06:00:00'
union all select
'2012-06-08 06:00:00',
NULL
union all select
'2012-06-08 02:00:00',
'2012-06-08 03:00:00'
union all select
'2012-01-01 14:09:00',
'2012-01-01 17:30:00'
union all select
'2012-01-01 18:30:00',
'2012-01-01 19:30:00';
WITH ClockData AS
(
SELECT ID, [Start], [End] AS EffectiveEnd, [Start] AS LastStart, 1 AS NumTimespans
FROM #TimeSheetEntries ts
WHERE NOT EXISTS
(
SELECT tsWhere.ID FROM #TimeSheetEntries tsWhere
WHERE
tsWhere.ID <> ts.ID -- don't match yourself!
AND tsWhere.[Start] < ts.[Start]
AND
(
-- Three types of things we don't want our outer SELECT to return
-- 1) Completed timespans with another appointment's end date sitting inside;
-- 2) Incomplete timespans (NULL ClockedOut) with another appointment's end date after ClockedIn
-- 3) Any timespan wholly inside another one
(ts.[End] IS NULL AND tsWhere.[End] >= ts.[Start]) OR
(ts.[End] IS NOT NULL AND tsWhere.[End] BETWEEN ts.[Start] AND ts.[End]) OR
(tswhere.[End] > ts.[End])
)
)
UNION ALL
SELECT cd.ID, cd.[Start], ts.[End] AS EffectiveClockout, ts.Start AS LastStart, cd.NumTimespans + 1 AS NumTimespans
FROM #TimeSheetEntries ts
INNER JOIN ClockData cd
ON ts.[Start] BETWEEN cd.[Start] AND cd.EffectiveEnd AND ts.ID <> cd.ID
AND (ts.[End] IS NULL OR ts.[End] > cd.EffectiveEnd)
),
MergedTimespans AS
(
SELECT [ID], [Start], [EffectiveEnd], [LastStart]
FROM ClockData cd
WHERE NumTimespans = (SELECT MAX(NumTimespans) FROM ClockData WHERE ID = cd.ID)
)
SELECT
CASE
WHEN mt.Start > cal.CalDate
THEN mt.Start
ELSE cal.CalDate
END AS [Start],
CASE
WHEN (mt.EffectiveEnd IS NOT NULL AND mt.EffectiveEnd >= DATEADD(day,1,cal.CalDate)) OR (mt.EffectiveEnd IS NULL AND cal.CalDate < CAST(mt.LastStart AS date)) THEN DATEADD(second, -1,DATEADD(day,1,cal.CalDate))
ELSE mt.EffectiveEnd
END AS [End]
FROM MergedTimespans mt
INNER JOIN #CalendarTable cal
ON (mt.EffectiveEnd IS NULL AND cal.CalDate BETWEEN CAST(mt.Start AS date) AND mt.LastStart) -- Handle NULL end dates
OR (mt.EffectiveEnd IS NOT NULL AND cal.CalDate BETWEEN CAST(mt.Start AS date) AND mt.EffectiveEnd)
ORDER BY Start
with cte
AS ( SELECT MIN(START) AS MinStart ,
MAX(START) AS MaxStart
FROM TableA
UNION ALL
SELECT DATEADD(DAY, 1, MinStart) ,
MaxStart
FROM cte
WHERE DATEADD(DAY, 1, MinStart) BETWEEN MinStart AND MaxStart
)
SELECT MinStart AS START ,
DATEADD(millisecond, -3, FLOOR(CAST(MinStart AS FLOAT)) + 1) AS [End]
FROM cte

Date comparing between two dates? [duplicate]

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

Resources