Select only value of given interval - sql-server

I am working on a SQL query where I have to select only one value of given time interval in seconds.
Suppose I give time interval=5, then the value should come after every 5 seconds. If I give time interval=60, then the value should come after every 60 seconds i.e. after every minute. If I give time interval=300, then the value should come after every 300 seconds i.e. after every 5 minutes and so on.
For this I used the following query
DECLARE #FROMDATETIME DATE = '2016-09-21 14:00',
#TODATETIME DATE = '2020-09-21 14:00',
#INTERVAL NVARCHAR(50) = '300'
DECLARE #intv INT = ((CONVERT(INT, #INTERVAL)) / 60)
SELECT
CONVERT(NVARCHAR(20), DATEANDTIME, 113) DATETIME,
ALARM, F870 'COLD JUICE PRE [PSI]',
F872 'COLD WATER PRE [PSI]', F82 'FILLER TEMP [DEGC]',
F810 'FLOW [LTR/MIN]', F869 'HOT JUICE PRE[PSI]',
F874 'HOT WATER PRE[PSI]', F867 'HOT WATER TEMP[DEGC]',
F84 'JUICE TEMP AFTER HOLD TUBE[DEGC]', F822 'PD FOR COLD PHE[PSI]',
F821 'PD FOR HOT PHE[PSI]', F8X 'PHE INLET TEMP[DEGC]',
B1 'MACHINE 1 STATUS', B2 'MACHINE 2 STATUS'
FROM
(SELECT
DATEANDTIME,
NULL ALARM, F870 F870, F872 F872, F82 F82, F810 F810, F869 F869,
F874 F874, F867 F867, F84 F84, F822 F822, F821 F821, F8X F8X,
CASE
WHEN B1 = 1 THEN 'ON'
ELSE 'OFF'
END B1,
CASE WHEN B2 = 1
THEN 'ON'
ELSE 'OFF'
END B2
FROM
DATALOGTABLE WITH (NOLOCK)
WHERE
(CONVERT(DATE, DATEANDTIME, 103) >= CONVERT(DATE, #FROMDATETIME, 103)
AND CONVERT(DATE, DATEANDTIME, 103) <= CONVERT(DATE, #TODATETIME, 103))
AND (((DATEPART(minute, dateandtime) % #intv) = 0))
UNION ALL
SELECT
DATEANDTIME, ALARMTXT ALARM,
NULL F870, NULL F872, NULL F82, NULL F810, NULL F869, NULL F874,
NULL F867, NULL F84, NULL F822, NULL F821, NULL F8X, NULL B1, NULL B2
FROM
DBO.ALARMHISTORY WITH (NOLOCK)
WHERE
(CONVERT(DATE, DATEANDTIME, 103) >= CONVERT(DATE, #FROMDATETIME, 103)
AND CONVERT(DATE, DATEANDTIME, 103) <= CONVERT(DATE, #TODATETIME, 103))
AND (((DATEPART(minute, dateandtime) % #intv) = 0))
) Z
ORDER BY
Z.DATEANDTIME DESC
In the above query I have given time interval of 300 second i.e. 5 minute means value should come after every 300 second or 5 minutes. But it is showing value of every minute.
09 Jan 2020 20:10:59 NULL 70.00 72.00 2.00 0.00 69.65
09 Jan 2020 20:10:58 NULL 70.00 72.00 2.00 0.00 69.65
09 Jan 2020 20:10:57 NULL 70.00 72.00 2.00 0.00 69.65
09 Jan 2020 20:10:56 NULL 70.00 72.00 2.00 0.00 69.65
09 Jan 2020 20:10:55 NULL 70.00 72.00 2.00 0.00 69.65
Here the first record have date '09 Jan 2020 20:10:59' and second should be
'09 Jan 2020 20:15:59' because interval given between two rows date is 300 seconds. which is not coming in this case. What to do here?

You seem try to mod minutes to seconds, you should correct this:
declare #DATETIME DATETIME = '2016-09-21 14:59:30';
declare #INTERVAL NVARCHAR(50) = '300'
select (DATEPART(minute, #DATETIME) * 60 + DATEPART(second, #DATETIME)) % #INTERVAL;

Related

Calculate time between startdate and enddate and subtracting days that have no worktime

My goal is to check if an email is answered within 24 hours during workdays. de definition of a workday is if there is time registered in another table. this because we sometimes work on a Saturday or a Sunday or to exclude holidays. I made a view from that table that gives a 1 if the date has worktime or a 0 if there is no worktime registered.
DateWorked
HasWorked
2021-04-01 00:00:00.000
1
2021-04-02 00:00:00.000
1
2021-04-03 00:00:00.000
1
2021-04-04 00:00:00.000
0
2021-04-05 00:00:00.000
1
So for example a few situations:
1. MailIncoming: 2021-04-01 16:30:00, MailAnswering: 2021-04-02 14:00:00
This one is easy, I don't have to subtract anything and the mail is answered within 24 hours.
2. MailIncoming: 2021-04-01 09:30:00, MailAnswering: 2021-04-03 14:00:00
This one is also easy, I don't have to subtract anything and the mail is not answered within 24 hours.
3. MailIncoming: 2021-04-03 12:30:00, MailAnswering: 2021-04-05 10:00:00
There is 1 day where no one has worked, so I need to subtract 1 whole day from the total time, and in that case the email is answered within 24 hours during workdays.
4. MailIncoming: 2021-04-04 11:00:00, MailAnswering: 2021-04-05 18:00:00
The remaining 13 hours from 04 do not count toward the '24 hours during workdays' so the email is answered within 24 during workdays.
Also, there can be multiple dates with zero after each other.
So the outcome I'm looking for is:
MailIncoming
MailAnswering
TotalTime
TotalTimeWithoutDaysNotWorked
2021-04-04 11:00:00.000
2021-04-05 18:00:00.000
31
18
How can I calculate this last column? Or am I approaching this in the wrong way?
The query needs a way to generate calculated dates between MailIncoming and MailAnswering so there can be a LEFT JOIN (or INNER JOIN) to the WorkingDay table. In this case the query uses dbo.fnTally which is known to be a fast and efficient way to generate rows.
tables
drop table if exists #WorkingDay;
go
create table #WorkingDay(
DateWorked Date,
HasNotWorked int);
drop table if exists #MailIncoming;
go
create table #MailIncoming(
MailIncoming DateTime,
MailAnswering DateTime);
insert into #WorkingDay values
('2021-04-01', 0),
('2021-04-02', 0),
('2021-04-03', 0),
('2021-04-04', 1),
('2021-04-05', 0),
('2021-04-06', 0);
insert into #MailIncoming values
('2021-04-01 16:30:00', '2021-04-02 14:00:00'),
('2021-04-01 09:30:00', '2021-04-03 14:00:00'),
('2021-04-03 12:30:00', '2021-04-05 10:00:00'),
('2021-04-04 11:00:00', '2021-04-05 18:00:00');
dbo.fnTally
CREATE FUNCTION [dbo].[fnTally]
/**********************************************************************************************************************
Jeff Moden Script on SSC: https://www.sqlservercentral.com/scripts/create-a-tally-function-fntally
**********************************************************************************************************************/
(#ZeroOrOne BIT, #MaxN BIGINT)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN WITH
H2(N) AS ( SELECT 1
FROM (VALUES
(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
)V(N)) --16^2 or 256 rows
, H4(N) AS (SELECT 1 FROM H2 a, H2 b) --16^4 or 65,536 rows
, H8(N) AS (SELECT 1 FROM H4 a, H4 b) --16^8 or 4,294,967,296 rows
SELECT N = 0 WHERE #ZeroOrOne = 0 UNION ALL
SELECT TOP(#MaxN)
N = ROW_NUMBER() OVER (ORDER BY N)
FROM H8
;
query
select mi.MailIncoming, mi.MailAnswering,
avg(datediff(hour, MailIncoming, MailAnswering)) hrs_to_ans,
sum(case when w.HasNotWorked=1 and
v.calc_dt > mi_dt.inc_dt and
v.calc_dt < mi_dt.ans_dt
then -24
when w.HasNotWorked=1
then datediff(hour, dateadd(day, 1, mi_dt.inc_dt), mi.MailIncoming)
else 0 end) hrs_to_sub
from #MailIncoming mi
cross apply (values (cast(MailIncoming as date),
cast(MailAnswering as date))) mi_dt(inc_dt, ans_dt)
cross apply dbo.fnTally(0, datediff(day, mi.MailIncoming, mi.MailAnswering)) fn
cross apply (values (dateadd(day, fn.n, mi_dt.inc_dt))) v(calc_dt)
left join #WorkingDay w on v.calc_dt=w.DateWorked
group by mi.MailIncoming, mi.MailAnswering
order by mi.MailIncoming;
MailIncoming MailAnswering hrs_to_ans hrs_to_sub
2021-04-01 09:30:00.000 2021-04-03 14:00:00.000 53 0
2021-04-01 16:30:00.000 2021-04-02 14:00:00.000 22 0
2021-04-03 12:30:00.000 2021-04-05 10:00:00.000 46 -24
2021-04-04 11:00:00.000 2021-04-05 18:00:00.000 31 -13
I suggest you to use a column HasNotWorked, so the tables are
create table WorkingDay(DateWorked Date, HasNotWorked int);
create table MailIncoming(MailIncoming DateTime, MailAnswering DateTime);
and the rows
insert into WorkingDay values('2021-04-01', 0);
insert into WorkingDay values('2021-04-02', 0);
insert into WorkingDay values('2021-04-03', 0);
insert into WorkingDay values('2021-04-04', 1);
insert into WorkingDay values('2021-04-05', 0);
insert into WorkingDay values('2021-04-06', 0);
insert into MailIncoming values('2021-04-04 11:00:00.000', '2021-04-06 18:00:00.000');
I want calculate the start date. If is in working day, we must consider the hour of the mail, else the first working day with
case when
(select HasNotWorked from WorkingDay where DateWorked = convert(date, MailIncoming)) = 1 then
(select min(DateWorked) from WorkingDay where DateWorked > MailIncoming and HasNotWorked = 0)
else MailIncoming end as startDate
and discard the day that are not working day
((select sum(HasNotWorked) from WorkingDay where DateWorked between convert(date, startDate)
and convert(date, MailAnswering)
) * 24) as numNotWorkingDay
so the query could be
select startDate, MailAnswering, MailIncoming, hour, numNotWorkingDay, hour - numNotWorkingDay hourWitoutWorkingDay
from (
select
MailAnswering, startDate, MailIncoming,
DateDiff("hh", startDate, MailAnswering) hour,
((select sum(HasNotWorked) from WorkingDay where DateWorked between convert(date, startDate)
and convert(date, MailAnswering)
) * 24) as numNotWorkingDay
from (
select *,
case when
(select HasNotWorked from WorkingDay where DateWorked = convert(date, MailIncoming)) = 1 then
(select min(DateWorked) from WorkingDay where DateWorked > MailIncoming and HasNotWorked = 0)
else MailIncoming end as startDate
from MailIncoming) as startCalc
) as calcTable;
sqlfiddle

Select part of duration that occurs in specific hour of day

In SQL Server, I have a table of processes with a starttime and an endtime, from which I can calculate a duration using DATEDIFF.
Name StartTime EndTime
------------------------------------------------
process1 2016-10-10 11:10 2016-10-10 11:20
process2 2016-10-10 11:40 2016-10-10 12:30
How can I select the timespan of the process duration that occured in specific hours of the day (11 and 12) in seconds?
So process1 would be 10 minutes in hour 11.
process2 would be 20 minutes in hour 11, 30 minutes in hour 12.
Here's a sample that will generate hourly records for each source record. It uses a recursive CTE to move from the StartTime of each record through the EndTime. It may need some slight modifications to make it work in your case, but hopefully you can get the idea of how this method works.
Note that, as shown in the sample below, this will work properly even if the time span crosses a date boundary.
--==================================================================================
-- Do some quick setup to get a temporary table populated with data to use:
--==================================================================================
IF OBJECT_ID('tempdb..#ProcessHistory', 'U') IS NOT NULL DROP TABLE #ProcessHistory;
CREATE TABLE #ProcessHistory (
Name VARCHAR(20),
StartTime DATETIME,
EndTime DATETIME
)
INSERT INTO #ProcessHistory
VALUES ('process1', '2016-10-10 11:10', '2016-10-10 11:20'),
('process2', '2016-10-10 11:40', '2016-10-10 12:30'),
('process3', '2016-10-10 22:21', '2016-10-11 02:36');
--==================================================================================
-- Use a recursive CTE to generate hourly data for each record:
--==================================================================================
WITH HourlyData AS (
-- Anchor:
SELECT
ph.Name [ProcessName],
ph.StartTime [StartTime],
ph.EndTime [EndTime],
-- Get the current hour with date:
DATEADD(MINUTE, -DATEPART(MINUTE, ph.StartTime), ph.StartTime) [CurrentHour],
-- Calculate the next hour for use later:
DATEADD(MINUTE, 60 - DATEPART(MINUTE, ph.StartTime), ph.StartTime) [NextHour],
-- Determine how many minutes the process was active this hour:
CASE
WHEN DATEDIFF(MINUTE, ph.StartTime, ph.EndTime) > 60 - DATEPART(MINUTE, ph.StartTime)
THEN 60 - DATEPART(MINUTE, ph.StartTime)
ELSE DATEDIFF(MINUTE, ph.StartTime, ph.EndTime)
END [Minutes]
FROM #ProcessHistory ph
UNION ALL
-- Recurse:
SELECT
hd.ProcessName,
hd.StartTime,
hd.EndTime,
hd.NextHour [CurrentHour],
DATEADD(HOUR, 1, hd.NextHour) [NextHour],
-- Determine how many minutes the process was active this hour:
CASE
WHEN DATEDIFF(MINUTE, hd.NextHour, hd.EndTime) < 60
THEN DATEDIFF(MINUTE, hd.NextHour, hd.EndTime)
ELSE 60
END
FROM HourlyData hd
WHERE hd.NextHour < hd.EndTime
)
SELECT
hd.ProcessName,
hd.CurrentHour [HourWithDate],
CONVERT(DATE, hd.CurrentHour) [Date],
DATEPART(HOUR, hd.CurrentHour) [Hour],
hd.Minutes
FROM HourlyData hd
ORDER BY
hd.ProcessName,
hd.CurrentHour;
The output from the above sample would look like this:
ProcessName HourWithDate Date Hour Minutes
process1 2016-10-10 11:00:00.000 2016-10-10 11 10
process2 2016-10-10 11:00:00.000 2016-10-10 11 20
process2 2016-10-10 12:00:00.000 2016-10-10 12 30
process3 2016-10-10 22:00:00.000 2016-10-10 22 39
process3 2016-10-10 23:00:00.000 2016-10-10 23 60
process3 2016-10-11 00:00:00.000 2016-10-11 0 60
process3 2016-10-11 01:00:00.000 2016-10-11 1 60
process3 2016-10-11 02:00:00.000 2016-10-11 2 36
To handle general cases, you could try something like
--drop table #processes
CREATE TABLE #processes
(
name varchar(50),
StartTime Datetime,
EndTime DateTime
);
insert #processes VALUES('proc1','20161010 11:10','20161010 11:20');
insert #processes VALUES('proc2','20161010 11:40','20161010 12:20');
insert #processes VALUES('proc3','20161010 10:40','20161010 12:20');
;WITH HRS AS (SELECT 0 HR
UNION ALL
SELECT HR + 1 FROM HRS WHERE HR < 23),
MINS AS (SELECT 0 MN
UNION ALL
SELECT MN + 1 FROM MINS WHERE MN < 59),
TIMES AS (SELECT HR,MN FROM HRS CROSS JOIN MINS)
SELECT name,starttime,endtime,Count(0) AS mins FROM #processes
JOIN TIMES
ON (HR > datepart(hh,Starttime)
OR HR = datepart(hh,Starttime) AND MN >= datepart(n,STARTtIME))
AND
(HR < datepart(hh, EndTime)
OR HR = datepart(hh, EndTime) AND MN < datepart(n,EndTime))
WHERE HR = 11 --hour is 11
GROUP BY name,
starttime,
endtime
drop table #processes;
create table #temp (Name varchar(5), starttime datetime, EndTime datetime)
insert into #temp values(1,'2016-10-10 11:10','2016-10-10 11:20' )
insert into #temp values(2,'2016-10-10 11:40','2016-10-10 12:30' )
insert into #temp values(2,'2016-10-10 10:40','2016-10-10 11:30' )
insert into #temp values(2,'2016-10-10 10:40','2016-10-10 12:30' )
DECLARE #firstTime time ,#secondTime time
set #firstTime ='11:00'
set #secondTime ='12:00'
select
CASE WHEN CONVERT(time(0), starttime) < #firstTime AND CONVERT(time(0), EndTime) > #secondTime THEN DATEDIFF(ss,#firstTime,#secondTime)
WHEN CONVERT(time(0), EndTime) > #secondTime THEN DATEDIFF(ss,CONVERT(time(0), starttime),#secondTime)
WHEN CONVERT(time(0), starttime) < #firstTime THEN DATEDIFF(ss,CONVERT(time(0), EndTime),#secondTime)
ELSE DATEDIFF(ss,starttime,EndTime)
END
from #temp
SELECT CAST(DATEADD(MINUTE,DATEDIFF(MINUTE,'2016-10-10 11:10','2016-10-10 12:20'),'2011-01-01 00:00:00.000') AS TIME)
as timeDifference
With timeDifference -
SELECT CAST(DATEADD(MINUTE,DATEDIFF(MINUTE,StartTime,EndTime),'2011-01-01 00:00:00.000') AS TIME)
as timeDifference
from #YourTableName
With Days and TimeDiffernece
declare #start_time as varchar(150);
declare #end_time as varchar(150);
set #start_time='2016-10-10 10:10';
set #end_time='2016-10-12 12:10'
SELECT datediff(day,#start_time,#end_time) as dayDifference,
CAST(DATEADD(MINUTE,DATEDIFF(MINUTE,#start_time,#end_time),'2011-01-01 00:00:00') AS TIME(0))
as timeDifference
I think this does the trick, but it's pretty ugly. Maybe someone can do it more elegantly?
SELECT
case
when HOUR(starttime) < 11 AND HOUR(endtime) = 11 then minute(endtime)
when HOUR(starttime) < 11 AND HOUR(endtime) > 11 then 60
when HOUR(starttime) = 11 AND HOUR(endtime) = 11 then minute(endtime) - minute(starttime)
when HOUR(starttime) = 11 AND HOUR(endtime) > 11 then 60 - minute(starttime)
else 0
end AS ProcessTimeHour_11,
case
when HOUR(starttime) < 12 AND HOUR(endtime) = 12 then minute(endtime)
when HOUR(starttime) < 12 AND HOUR(endtime) > 12 then 60
when HOUR(starttime) = 12 AND HOUR(endtime) = 12 then minute(endtime) - minute(starttime)
when HOUR(starttime) = 12 AND HOUR(endtime) > 12 then 60 - minute(starttime)
else 0
end AS ProcessTimeHour_12
from StuffAndThings

How can I show all time between 2 different time parameter

I have 3 Columns in db Time Parameter(00:15) , StartTime(09:00) , EndTime (15:00)
Now I want to show all time with gap of 00:15 min between 09:00 and 15:00
What query should I write so that it returns values something like this:
09:00 - 09:15
09:15 - 09:30
09:30 - 09:45
-
-
-
-
14:45 - 15:00
Using CTE and assuming hour part of #time is zero:
declare #time time(0) = '00:15',
#start time(0) = '12:00',
#end time(0) = '15:00'
;with cte as (
select #start sTime, dateadd(minute, datepart(minute,#time), #start) eTime
union all
select eTime, dateadd(minute, datepart(minute,#time), eTime)
from cte
where dateadd(minute, datepart(minute,#time), eTime) <= #end
)
select left(sTime,5) + ' - ' + left(eTime, 5) results
from cte
--results
12:00 - 12:15
12:15 - 12:30
12:30 - 12:45
12:45 - 13:00
13:00 - 13:15
13:15 - 13:30
13:30 - 13:45
13:45 - 14:00
14:00 - 14:15
14:15 - 14:30
14:30 - 14:45
14:45 - 15:00
Use a Common table expression (CTE) to generate a table with all the times in it that you want.
Declare #strtDt smallDatetime = '15 May 2013 09:00';
Declare #endDt smallDateTime = '15 May 2013 15:00';
With DateTimes(dt) As
(Select #strtDt
Union All
Select DateAdd(minute, 15, dt)
From DateTimes
Where dt < #endDt)
Select dt from DateTimes
option (maxrecursion 10000)

DATEDIFF with cutoff time

I'm working on a Room Scheduling application. We have this Room Check Out Rule that we need follow. All
room check out should be 12:00 PM. If the check out date is after 12.00 PM it will be considered additional 1 day.
Below is my T-SQL code that returns 5 days.
SELECT DATEDIFF(day, '3/12/2013 12:00:00 PM', '3/17/2013 3:00:00 PM');
If you see the code above the end date is 3:00:00 PM. How can I tweak this code to return 6 days instead of 5?
What if I have this code?
SELECT CEILING(DATEDIFF(SECOND, '3/12/2013 02:00:00 PM' , '3/17/2013 12:50:36 PM') / (24.0 * 60 * 60))
The above code still returns 5 days instead of 6.
SELECT CEILING(DATEDIFF(SECOND, '3/12/2013 12:00:00 PM', '3/17/2013 12:00:01 PM') / (24.0 * 60 * 60))
The correct way is to subtract 12 hours from StartDate and EndDate, then take a day-diff + 1:
declare #dateStart as datetime, #dateEnd as datetime
set #dateStart = cast('20130301 11:59:59 AM' as datetime)
set #dateEnd = cast('20130301 12:01:01 PM' as datetime)
select
#dateStart,
#dateEnd
select days = 1 + datediff(d,#dateStart,#dateEnd)
select
days = 1 + datediff(d, dateadd(hh, -12, #dateStart), dateadd(hh, -12, #dateEnd))
returns this:
----------------------- -----------------------
2013-03-01 11:59:59.000 2013-03-01 12:01:01.000
days
-----------
1
days
-----------
2
Clearly the second formula is correct, not the first.
Perhaps you can count hours:
SELECT DATEDIFF(hour, '3/12/2013 12:00:00 PM', '3/17/2013 3:00:00 PM');
Therefore, 123 > 120 (or divided by 24 - 5.125 > 5) accounts for 6 days.

Calculate total running time from start/stop timestamps

I have a table containing a number of timestamps per day, they represents start and stop events.
ID TimeStamp
----------------------
1 2008-01-01 07:00:00
1 2008-01-01 08:15:00
1 2008-01-01 10:00:00
1 2008-01-01 11:00:00
1 2008-01-02 10:30:00
1 2008-01-02 12:00:00
I would like to calcuate the total running time per day, like this:
ID Date RunningTime
-------------------------
1 2008-01-01 02:15:00
1 2008-01-02 01:30:00
Do anyone have a nice T-SQL solution for my problem?
WITH q AS
(
SELECT *,
CONVERT(DATETIME, CONVERT(VARCHAR(8), TimeStamp, 112), 112) AS dte,
ROW_NUMBER() OVER (PARTITION BY id, CONVERT(DATETIME, CONVERT(VARCHAR(8), TimeStamp, 112), 112) ORDER BY TimeStamp) AS rn
FROM mytable
)
SELECT qb.id, qb.dte, SUM(DATEDIFF(second, qb.TimeStamp, qe.TimeStamp))
FROM q qb
JOIN q qe
ON qe.id = qb.id
AND qe.dte = qb.dte
AND qe.rn = qb.rn + 1
WHERE qb.rn % 2 = 1
GROUP BY
qb.id, qb.dte
This assumes that every record open on a certain day should also be closed on the same day.

Resources