I have below table structure in SQL Server:
StartDate Start End Sales
==============================================
2020-08-25 00:00:00 00:15:00 291.4200
2020-08-25 00:15:00 00:30:00 401.1700
2020-08-25 00:30:00 00:45:00 308.3300
2020-08-25 00:45:00 01:00:00 518.3200
2020-08-25 01:00:00 01:15:00 247.3700
2020-08-25 01:15:00 01:30:00 115.4700
2020-08-25 01:30:00 01:45:00 342.3800
2020-08-25 01:45:00 02:00:00 233.0900
2020-08-25 02:00:00 02:15:00 303.3400
2020-08-25 02:15:00 02:30:00 11.9000
2020-08-25 02:30:00 02:45:00 115.2400
2020-08-25 02:45:00 03:00:00 199.5200
2020-08-25 06:00:00 06:15:00 0.0000
2020-08-25 06:15:00 06:30:00 45.2400
2020-08-25 06:30:00 06:45:00 30.4800
2020-08-25 06:45:00 07:00:00 0.0000
2020-08-25 07:00:00 07:15:00 0.0000
2020-08-25 07:15:00 07:30:00 69.2800
Is there a way to group above data into one hour interval instead of 15 minute interval?
It has to be based on start and end columns.
Thanks,
Maybe something like the following using datepart?
select startdate, DatePart(hour,start) [Hour], Sum(sales) SalesPerHour
from t
group by startdate, DatePart(hour,start)
I have a table that needs to be updated with the values from the same table. Basically, I want to change the connection setup in the rows where the worker and client are same and that the changed row Connection setup started in 5mins after the other connection (with the same worker and client) ended.
The code below does this.
But there is one more problem. when there are multiple connections that happen in short period of time , between the same client and worker I need them all to have the same Connection setup.
I really am not sure how to achieve this.
the current query:
UPDATE t
SET t.[Connection setup] = t2.[Connection setup]
FROM Table1 t
INNER JOIN Table1 t2 ON t.worker = t2.worker
AND t.client = t2.client
AND t.SessionNo <> t2.SessionNo
AND t.[Connection setup] <= DATEADD(mi, 5, t2.[Connection end])
AND t.[Connection setup] >= t2.[Connection end]
As you can see in this example there are several connections between same client and worker and the column "real_time" shows what time they should have.
SessionNo worker Tag Start Ende Dauer Connection setup Connection end client right_time
5 116590 mma 09.08.2020 00:00:00 12:44 13:01 00:17 09.08.2020 12:44:00 09.08.2020 13:01:00 OBENAT1D0137 12:44
6 106991 mma 09.08.2020 00:00:00 13:03 13:07 00:04 09.08.2020 13:03:00 09.08.2020 13:07:00 OBENAT1D0137 12:44
7 102306 mma 09.08.2020 00:00:00 13:07 13:56 00:49 09.08.2020 13:07:00 09.08.2020 13:56:00 OBENAT1D0137 12:44
8 430386 mma 09.08.2020 00:00:00 13:56 14:06 00:10 09.08.2020 13:56:00 09.08.2020 14:06:00 OBENAT1D0137 12:44
9 117264 mma 09.08.2020 00:00:00 14:06 14:17 00:10 09.08.2020 14:06:00 09.08.2020 14:17:00 OBENAT1D0137 12:44
10 434302 mma 09.08.2020 00:00:00 14:17 14:41 00:23 09.08.2020 14:17:00 09.08.2020 14:41:00 OBENAT1D0137 12:44
11 333234 mma 09.08.2020 00:00:00 14:41 14:55 00:13 09.08.2020 14:41:00 09.08.2020 14:55:00 OBENAT1D0137 12:44
12 271379 mg 09.03.2020 00:00:00 10:24 10:25 00:00 09.03.2020 10:24:00 09.03.2020 10:25:00 OBENAT1D0117 10:24
13 269650 mg 09.03.2020 00:00:00 10:25 10:47 00:21 09.03.2020 10:25:00 09.03.2020 10:47:00 OBENAT1D0117 10:24
14 290765 mg 09.03.2020 00:00:00 12:19 12:19 00:00 09.03.2020 12:19:00 09.03.2020 12:19:00 OBENAT1D0117 12:19
15 280892 mg 09.03.2020 00:00:00 12:19 12:22 00:03 09.03.2020 12:19:00 09.03.2020 12:22:00 OBENAT1D0117 12:19
with my current query they just take the time from the row before.
any help would be great
EDIT : I added 4 rows to the table to explain the problem more in detail. For example in the last 4 rows the client and worker are the same, but the connections should be grouped in 2 different groups. not in one. as it can be seen by the column "right_time".
One option to group the rows would be to use recursion. However, recursion can be slow on large data sets...
Sample data
I omitted some columns from your sample data and only used the columns I need and added an id column for the initial values. If the id column is not part of your data set, then you will have to compare both conn_start and conn_end to sort of find the next row for each combination of worker and client (because there can be rows with an equal conn_start value like rows 14 and 15).
create table data
(
id int,
worker nvarchar(3),
client nvarchar(15),
conn_start datetime2(0),
conn_end datetime2(0)
);
insert into data (id, worker, client, conn_start, conn_end) values
(5 , 'mma', 'OBENAT1D0137', '09.08.2020 12:44:00', '09.08.2020 13:01:00'),
(6 , 'mma', 'OBENAT1D0137', '09.08.2020 13:03:00', '09.08.2020 13:07:00'),
(7 , 'mma', 'OBENAT1D0137', '09.08.2020 13:07:00', '09.08.2020 13:56:00'),
(8 , 'mma', 'OBENAT1D0137', '09.08.2020 13:56:00', '09.08.2020 14:06:00'),
(9 , 'mma', 'OBENAT1D0137', '09.08.2020 14:06:00', '09.08.2020 14:17:00'),
(10, 'mma', 'OBENAT1D0137', '09.08.2020 14:17:00', '09.08.2020 14:41:00'),
(11, 'mma', 'OBENAT1D0137', '09.08.2020 14:41:00', '09.08.2020 14:55:00'),
(12, 'mg', 'OBENAT1D0117', '09.03.2020 10:24:00', '09.03.2020 10:25:00'),
(13, 'mg', 'OBENAT1D0117', '09.03.2020 10:25:00', '09.03.2020 10:47:00'),
(14, 'mg', 'OBENAT1D0117', '09.03.2020 12:19:00', '09.03.2020 12:19:00'),
(15, 'mg', 'OBENAT1D0117', '09.03.2020 12:19:00', '09.03.2020 12:22:00');
Solution
If this looks daunting, then make sure to check out this fiddle for a step-by-step construction.
with cte as
(
select d.id,
d.worker,
d.client,
d.conn_start,
d.conn_end,
datediff(minute,
coalesce(lag(d.conn_end) over(partition by d.worker, d.client order by d.id), d.conn_start),
d.conn_start) as diff_minutes
from data d
),
rcte as
(
select c.id,
c.worker,
c.client,
c.conn_start,
c.conn_end,
c.diff_minutes,
c.conn_start as conn_start_group
from cte c
where not exists ( select 'x'
from data d2
where d2.worker = c.worker
and d2.client = c.client
and d2.id < c.id )
union all
-- select next row for each (worker, client), keep conn_start_group if difference < 5 min
select c.id,
c.worker,
c.client,
c.conn_start,
c.conn_end,
c.diff_minutes,
case
when c.diff_minutes <= 5
then r.conn_start_group
else c.conn_start
end
from rcte r
join cte c
on c.worker = r.worker
and c.client = r.client
and c.id > r.id
and not exists ( select 'x'
from cte c2
where c2.worker = c.worker
and c2.client = c.client
and c2.id > r.id
and c2.id < c.id )
)
select rc.id,
rc.worker,
rc.client,
rc.conn_start,
rc.conn_end,
rc.conn_start_group
from rcte rc
order by rc.id;
Result
id worker client conn_start conn_end conn_start_group
-- ------ ------------ ------------------- ------------------- -------------------
5 mma OBENAT1D0137 2020-09-08 12:44:00 2020-09-08 13:01:00 2020-09-08 12:44:00
6 mma OBENAT1D0137 2020-09-08 13:03:00 2020-09-08 13:07:00 2020-09-08 12:44:00
7 mma OBENAT1D0137 2020-09-08 13:07:00 2020-09-08 13:56:00 2020-09-08 12:44:00
8 mma OBENAT1D0137 2020-09-08 13:56:00 2020-09-08 14:06:00 2020-09-08 12:44:00
9 mma OBENAT1D0137 2020-09-08 14:06:00 2020-09-08 14:17:00 2020-09-08 12:44:00
10 mma OBENAT1D0137 2020-09-08 14:17:00 2020-09-08 14:41:00 2020-09-08 12:44:00
11 mma OBENAT1D0137 2020-09-08 14:41:00 2020-09-08 14:55:00 2020-09-08 12:44:00
12 mg OBENAT1D0117 2020-09-03 10:24:00 2020-09-03 10:25:00 2020-09-03 10:24:00
13 mg OBENAT1D0117 2020-09-03 10:25:00 2020-09-03 10:47:00 2020-09-03 10:24:00
14 mg OBENAT1D0117 2020-09-03 12:19:00 2020-09-03 12:19:00 2020-09-03 12:19:00
15 mg OBENAT1D0117 2020-09-03 12:19:00 2020-09-03 12:22:00 2020-09-03 12:19:00
This should work. I used the following table so you may need to adjust the code to get it to work with your actual table. The column [ConnSetupCalc] was used to test the calculation rather than updating the actual data during testing and then having to re-create the correct data.
CREATE TABLE [dbo].[conn_data](
[SessionNo] [int] NULL,
[worker] [nvarchar](3) NULL,
[client] [nvarchar](15) NULL,
[ConnectionSetup] [datetime2](0) NULL,
[ConnectionEnd] [datetime2](0) NULL,
[RightTime] [nvarchar](15) NULL,
[ConnSetupCalc] [datetime] NULL
)
This Stored Proc should calculate the data in line with your example:
CREATE PROCEDURE UpdConn
AS
declare #MyCursor CURSOR;
declare #SessionNo int;
declare #Worker nvarchar(3);
declare #Client nvarchar(15);
declare #ConnStart datetime;
declare #ConnEnd datetime;
declare #Worker_prev nvarchar(3);
declare #Client_prev nvarchar(15);
declare #ConnStart_prev datetime;
declare #ConnEnd_prev datetime;
BEGIN
SET #MyCursor = CURSOR FOR
SELECT SessionNo
,worker
,client
,ConnectionSetup
,ConnectionEnd
FROM [dbo].[conn_data]
order by worker, client, ConnectionSetup
OPEN #MyCursor
FETCH NEXT FROM #MyCursor
INTO #SessionNo, #Worker, #Client, #ConnStart, #ConnEnd
WHILE ##FETCH_STATUS = 0
BEGIN
IF #Worker = #Worker_prev and #Client = #Client_prev and DATEDIFF(mi,#ConnEnd_prev,#ConnStart) between 0 and 5
BEGIN
UPDATE conn_data set ConnectionSetup = #ConnStart_prev where SessionNo = #SessionNo;
-- Test logic: UPDATE conn_data set ConnSetupCalc = #ConnStart_prev where SessionNo = #SessionNo;
END
ELSE
BEGIN
set #ConnStart_prev = #ConnStart;
END
SET #Worker_prev = #Worker;
SET #Client_prev = #Client;
SET #ConnEnd_prev = #ConnEnd;
FETCH NEXT FROM #MyCursor
INTO #SessionNo, #Worker, #Client, #ConnStart, #ConnEnd
END;
CLOSE #MyCursor ;
DEALLOCATE #MyCursor;
END;
I have an Excel sheet like the following:
ID Arrival Passed Berthing Date UnBerthing Date Departure Passed
1 13/05/2017 15:30 13/05/2017 16:00 31/05/2017 20:44 31/05/2017
2 15/05/2017 16:56 15/05/2017 17:15 16/05/2017 00:00 16/05/2017
3 20/05/2017 09:54 20/05/2017 10:26 20/05/2017 18:07 20/05/2017
4 24/05/2017 16:09 24/05/2017 16:35 25/05/2017 01:03 25/05/2017
5 29/05/2017 10:30 29/05/2017 10:45 29/05/2017 17:33 29/05/2017
I need this in the following format:
ID Event Time
1 Arrival 13/05/2017 15:30
1 Berth 13/05/2017 16:00
1 UnBerth 31/05/2017 20:44
1 Departure 31/05/2017 20:58
2 Arrival 15/05/2017 16:56
2 Berth 15/05/2017 17:15
2 UnBerth 16/05/2017 00:00
2 Departure 16/05/2017 00:04
etc
I've searched the web and this site(youtube...), but with no right answer, i've tried the transpose function and pivot table, but i couldn't make it.
Any help would be appreciated.
Thanks you.
Assuming that your dataset is in range A2:E6.
For getting ID:
=INDEX($A$2:$E$6,CEILING(ROWS($A$1:A1)/4,1),1)
For getting Event:
=CHOOSE(MOD(ROWS($A$1:A1)-1,4)+1,"Arrival","Berth","Unberth","Departure")
For getting Time:
=INDEX($A$2:$E$6,CEILING(ROWS($A$1:A1)/4,1),MOD(ROWS($A$1:A1)-1,4)+2)
and then copy down until you get error.
I have a data set:
tbldataid TS EndTS
> HX32.3401 10/2/2017 11:49:34 PM 10/3/2017 12:01:57 AM
> HX32.3403 10/3/2017 12:02:48 AM 10/3/2017 12:08:34 AM
> HX32.3425 10/3/2017 2:50:57 AM 10/3/2017 2:50:58 AM
> HX32.3428 10/3/2017 4:06:15 AM 10/3/2017 6:09:19 AM
I would like to to essentially 'split' these intervals on the hour, such as:
tbldataid TS EndTS
HX32.3401 10/2/2017 11:49:34 PM 10/2/2017 11:59:99 PM
HX32.3401 10/2/2017 12:00:00 PM 10/3/2017 12:01:57 AM
HX32.3403 10/3/2017 12:02:48 AM 10/3/2017 12:08:34 AM
HX32.3425 10/3/2017 2:50:57 AM 10/3/2017 2:50:58 AM
HX32.3428 10/3/2017 4:06:15 AM 10/3/2017 4:59:99 AM
HX32.3428 10/3/2017 5:00:00 AM 10/3/2017 5:59:99 AM
HX32.3428 10/3/2017 6:00:00 AM 10/3/2017 6:09:19 AM
Here is my code so far (credit for the idea goes to #Dumitrescu Bogdan, Split call data to 15 minute intervals):
SELECT [tbldataid],[TS],
IIF([EndTS]<=dateadd("n",60*((datediff("n",0,[TS]/60))+.99),0),
[EndTS],
dateadd("n", 60*(datediff("n",0,[TS]/60)+.99),0))
as [End]
FROM tbldata
UNION ALL
SELECT t2.[tbldataid], t2.[TS],
IIF(t1.[EndTS]<=dateadd("n",60*((datediff("n",0, t2.[EndTS])/60)+1),0),
t1.[EndTS],
dateadd("n",60*((datediff("n",0,t2.[EndTS])/60)+1),0))
as [End]
FROM
tbldata t1
LEFT JOIN tbldata t2
ON t1.[tbldataid]=t2.[tbldataid]
Where t2.[EndTS]<IIF(t1.[EndTS]<=dateadd("n",60*((datediff("n",0,t2.[EndTS])/60)+1),0),
t1.[EndTS],
dateadd("n",60*((datediff("n",0,t2.[EndTS])/60)+1),0));
The second half (after 'union all') doesn't produce any result, the first half produces the following:
tbldataid TS End
HX32.3401 10/2/2017 11:49:34 PM 10/2/2017 11:59:00 PM
HX32.3403 10/3/2017 12:02:48 AM 10/3/2017 12:08:34 AM
HX32.3425 10/3/2017 2:50:57 AM 10/3/2017 2:50:58 AM
HX32.3428 10/3/2017 4:06:15 AM 10/3/2017 4:59:00 AM
Thanks, I'm a beginner. I understand the first part; admittedly I don't understand the second half
I'm open to other solutions.
I'm using MS-Access 2010
This can be done with a Cartesian query:
SELECT DISTINCT
tblData.tblDataId,
IIf([TimeStart] > DateAdd("h",[Factor],CDate(Fix([Timestart]*24)/24)),
[TimeStart],
DateAdd("h",[Factor],CDate(Fix([Timestart]*24)/24))) AS TSStart,
IIf([TimeEnd] < DateAdd("s",3599,DateAdd("h",[Factor],CDate(Fix([Timestart]*24)/24))),
[TimeEnd],
DateAdd("s",3599,DateAdd("h",[Factor],CDate(Fix([Timestart]*24)/24)))) AS TSEnd
FROM
qdxFactor,
tblData
WHERE
qdxFactor.Factor Between 0 And DateDiff("h",[TimeStart],[TimeEnd]);
using this other saved Cartesian query (qdxFactor):
SELECT DISTINCT
[Tens]+[Ones] AS Factor,
10*Abs([Deca].[id] Mod 10) AS Tens,
Abs([Uno].[id] Mod 10) AS Ones
FROM
MSysObjects AS Uno,
MSysObjects AS Deca;
Result:
tblDataId TSStart TSEnd
3401 2017-10-02 23:49:34 2017-10-02 23:59:59
3401 2017-10-03 00:00:00 2017-10-03 00:01:57
3403 2017-10-03 00:02:48 2017-10-03 00:08:34
3425 2017-10-03 02:50:57 2017-10-03 02:50:58
3428 2017-10-03 04:06:15 2017-10-03 04:59:59
3428 2017-10-03 05:00:00 2017-10-03 05:59:59
3428 2017-10-03 06:00:00 2017-10-03 06:09:19
Second example with:
tblDataId TimeStart TimeEnd
3430 2017-10-07 02:08:24 2017-10-07 14:09:30
Result:
tblDataId TSStart TSEnd
3430 2017-10-07 02:08:24 2017-10-07 02:59:59
3430 2017-10-07 03:00:00 2017-10-07 03:59:59
3430 2017-10-07 04:00:00 2017-10-07 04:59:59
3430 2017-10-07 05:00:00 2017-10-07 05:59:59
3430 2017-10-07 06:00:00 2017-10-07 06:59:59
3430 2017-10-07 07:00:00 2017-10-07 07:59:59
3430 2017-10-07 08:00:00 2017-10-07 08:59:59
3430 2017-10-07 09:00:00 2017-10-07 09:59:59
3430 2017-10-07 10:00:00 2017-10-07 10:59:59
3430 2017-10-07 11:00:00 2017-10-07 11:59:59
3430 2017-10-07 12:00:00 2017-10-07 12:59:59
3430 2017-10-07 13:00:00 2017-10-07 13:59:59
3430 2017-10-07 14:00:00 2017-10-07 14:09:30
I have a table listing patient days for encounters. Below a sample for one encounter. Every day the patient is in the hospital one record is created at midnight untill discharge.
Enc_iD Day_Id ServiceDtTm AdmitDate
2616350 34707672 2/21/2013 23:59 21/FEB/13 12:19:00
2616350 34733898 2/22/2013 23:59 21/FEB/13 12:19:00
2616350 34748155 2/23/2013 23:59 21/FEB/13 12:19:00
2616350 34760403 2/24/2013 23:59 21/FEB/13 12:19:00
2616350 34784357 2/25/2013 23:59 21/FEB/13 12:19:00
2616350 34808228 2/26/2013 23:59 21/FEB/13 12:19:00
2616350 34814512 2/27/2013 10:10 21/FEB/13 12:19:00
In a separate table a status for every encounter is maintained irregulary by a user.
Enc_iD TransDtTm Status
2616350 2/21/2013 12:20
2616350 2/21/2013 13:29 1
2616350 2/22/2013 7:28 3
2616350 2/25/2013 13:44 2
2616350 2/27/2013 10:10 2
I want to create a resultset with SQL as below. So for every day in the top table the status that was the most recent at that ServiceDtTm.
Enc_iD Day_Id DtTime AdmitDate Status
2616350 34707672 2/21/2013 23:59 21/FEB/13 12:19:00 1
2616350 34733898 2/22/2013 23:59 21/FEB/13 12:19:00 3
2616350 34748155 2/23/2013 23:59 21/FEB/13 12:19:00 3
2616350 34760403 2/24/2013 23:59 21/FEB/13 12:19:00 3
2616350 34784357 2/25/2013 23:59 21/FEB/13 12:19:00 2
2616350 34808228 2/26/2013 23:59 21/FEB/13 12:19:00 2
2616350 34814512 2/27/2013 10:10 21/FEB/13 12:19:00 2
Any help is appreciated. Can't figure this out SQL. Only in excel by using vlookup with approximate match.
Robbert
I think the simplest solution is a correlated subquery. Here is the syntax in SQL Server:
select pd.*,
(select top 1 status
from status s
where s.enc_id = pd.enc_id and s.transdttm <= pd.servicedttm
order by s.transdttm
) as MostRecentStatus
from patientdays pd
For most other databases, it would look like:
select pd.*,
(select status
from status s
where s.enc_id = pd.enc_id and s.transdttm <= pd.servicedttm
order by s.transdttm
limit 1
) as MostRecentStatus
from patientdays pd