join status history - sql

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

Related

Group split data in timeline data in to one in PostgreSQL

I have data which is shown below.
stationName
status
startTime
endTime
A
normal
09:00
09:10
A
normal
09:10
09:20
B
normal
09:30
09:40
A
normal
09:30
09:40
B
normal
09:40
09:45
A
warning
09:40
09:45
B
warning
09:45
09:55
A
alert
09:45
09:55
B
normal
09:55
10:05
A
alert
09:55
10:05
B
normal
10:05
10:15
A
normal
10:05
10:15
B
normal
10:15
10:25
A
normal
10:15
10:25
B
normal
10:25
10:35
A
normal
10:25
10:35
and I want to query data into this structure
stationName
status
startTime
endTime
A
normal
09:00
09:40
A
warning
09:40
09:45
A
alert
09:45
10:05
A
normal
10:05
10:35
B
normal
09:30
09:45
B
warning
09:45
09:55
B
normal
09:55
10:35
My data timeline data is split into many parts, but I want to group it into one.
demo
idea: construct a range, test (startTime,endTime) belong to one specific timestamptz range or not,
then group by stationname, status, range(startTime, endTime) belong to.
I would use timestamptz type for startTime, endTime, tstzrange.
If you construct timerange, then range (23:00,0:00) is invalid.
table structure:
CREATE TABLE test102 (
stationName text,
status text,
startTime timestamptz,
endTime timestamptz
);
then query:
WITH cte AS (
SELECT
test102.*,
tstzrange(startTime, endTime) tstzrange_se,
tstzrange(i - interval '1 hour', i)
FROM
test102,
generate_series('2022-05-02'::timestamp, '2022-05-02'::timestamp + interval '24 hour', interval '1 hour') i
)
SELECT
stationname,
status,
min(startTime),
max(endTime)
FROM
cte
WHERE
tstzrange_se <# tstzrange
GROUP BY
1,
2,
tstzrange;

get time series in 8 hours of interval

I am generating one time-series from using the below query.
SELECT * from (
select * from generate_series(
date_trunc('hour', '2021-11-13 10:01:38'::timestamp),
'2021-12-13 10:01:38'::timestamp,
concat(480, ' minutes')::interval) as t(time_ent)) as t
where t."time_ent" between '2021-11-13 10:01:38'::timestamp and '2021-12-13 10:01:38'::timestamp
and it will give me output like below.
2021-11-13 18:00:00.000
2021-11-14 02:00:00.000
2021-11-14 10:00:00.000
2021-11-14 18:00:00.000
2021-11-15 02:00:00.000
but I need output like.
2021-11-13 16:00:00.000
2021-11-14 00:00:00.000
2021-11-14 08:00:00.000
2021-11-14 16:00:00.000
2021-11-15 00:00:00.000
currently, the time series hours depend upon the timestamp that I pass. in above it gives me hours like 02,10,18...but I want the hours like 00,08,16...hours should not depend on the time I passed in query. I tried many things but not any success.
as your start of generate_series is set to 10:00:00, so your next step will be 18:00:00
you have to start your serie from 00:00:00 (cast to date) e.g.:
SELECT
time_ent::timestamp without time zone
from (
select * from generate_series(
date_trunc('hour', '2021-11-13 10:01:38'::date),
'2021-12-13 10:01:38'::timestamp ,
concat(480, ' minutes')::interval) as t(time_ent)
) as t
where t."time_ent" between '2021-11-13 10:01:38'::timestamp and '2021-12-13 10:01:38'::timestamp
and the result will be:
2021-11-13 16:00:00.000
2021-11-14 00:00:00.000
2021-11-14 08:00:00.000
2021-11-14 16:00:00.000
2021-11-15 00:00:00.000
2021-11-15 08:00:00.000

SQL Server : update query doesn't change anything, shows no error

I am trying to update the table with the values from the same table.
What I want is 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.
I first created a SELECT query that returned me all the rows that needed to be changed
SELECT t.*
FROM Table1 t
WHERE EXISTS (SELECT 1 FROM Table1
WHERE worker = t.worker
AND client = t.client
AND t.SessionNo != SessionNo
AND t.[Connection setup] <= DATEADD(mi, 5, [Connection end])
AND t.[Connection setup] >= [Connection end])
Then I tried to import this query inside of an UPDATE query, but it didn't change anything :/ and it doesn't show me any errors.
UPDATE t
SET t.Start = t2.Start
FROM Table1 t
INNER JOIN Table1 t2 ON (t.SessionNo = t2.SessionNo)
WHERE t.worker = t2.worker
AND t.client = t2.client
AND t2.SessionNo <> t.SessionNo
AND t.[Connection setup] <= DATEADD(mi, 5, t2.[Connection end])
AND t.[Connection setup] >= t2.[Connection end]
Example:
The first table are the rows that should be changed. As you can see there is a column "right time" that shows what value should they have after the update.
SessionNo worker Tag Start Ende Dauer Connection setup Connection end client right_time
1 424568 mh 09.01.2020 00:00:00 13:45 13:49 00:04 09.01.2020 13:45:00 09.01.2020 13:49:00 OBENAT1D0209 13:44
2 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
3 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
4 175250 mg 09.03.2020 00:00:00 13:12 13:13 00:01 09.03.2020 13:12:00 09.03.2020 13:13:00 ORTNERAT1D0001 13:04
5 332684 dg 09.05.2020 00:00:00 16:05 16:33 00:28 09.05.2020 16:05:00 09.05.2020 16:33:00 KILLYAT3D0102 15:57
but as you can see here Start column is still the same.
SessionNo worker Tag Start Ende Dauer Connection setup Connection end client right_time
1 317045 mh 09.01.2020 00:00:00 09:29 09:38 00:09 09.01.2020 09:29:00 09.01.2020 09:38:00 AUMAAT1D0124 09:29
2 144035 sb 09.01.2020 00:00:00 11:09 11:27 00:18 09.01.2020 11:09:00 09.01.2020 11:27:00 OBENAT1D0231 11:09
3 437704 mh 09.01.2020 00:00:00 13:44 13:44 00:00 09.01.2020 13:44:00 09.01.2020 13:44:00 OBENAT1D0209 13:44
4 424568 mh 09.01.2020 00:00:00 13:45 13:49 00:04 09.01.2020 13:45:00 09.01.2020 13:49:00 OBENAT1D0209 13:44
5 219640 mh 09.01.2020 00:00:00 15:16 15:26 00:10 09.01.2020 15:16:00 09.01.2020 15:26:00 OBENAT1D0209 15:16
6 201023 mh 09.01.2020 00:00:00 16:29 16:35 00:06 09.01.2020 16:29:00 09.01.2020 16:35:00 OBENAT1D0209 16:29
7 236114 mg 09.03.2020 00:00:00 08:55 09:08 00:12 09.03.2020 08:55:00 09.03.2020 09:08:00 NULL NULL
8 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
9 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
10 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
11 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
12 538583 mg 09.03.2020 00:00:00 12:30 12:58 00:28 09.03.2020 12:30:00 09.03.2020 12:58:00 RATTAYAT1D0107 NULL
13 697202 mg 09.03.2020 00:00:00 13:04 13:08 00:04 09.03.2020 13:04:00 09.03.2020 13:08:00 ORTNERAT1D0001 13:04
14 175250 mg 09.03.2020 00:00:00 13:12 13:13 00:01 09.03.2020 13:12:00 09.03.2020 13:13:00 ORTNERAT1D0001 13:04
15 330580 dg 09.05.2020 00:00:00 15:57 16:05 00:08 09.05.2020 15:57:00 09.05.2020 16:05:00 KILLYAT3D0102 15:57
16 332684 dg 09.05.2020 00:00:00 16:05 16:33 00:28 09.05.2020 16:05:00 09.05.2020 16:33:00 KILLYAT3D0102 15:57
NOTE : In this case, in order to test the values I am changing the Start column instead of the connection startup.
You are updating zero rows, because of:
ON (t.SessionNo = t2.SessionNo)
...
AND t2.SessionNo <> t.SessionNo
You want to find rows with another session number, but you have t.SessionNo = t2.SessionNo, so this is exactly what you don't want.
You seem to think that a join needs a comparision with = on a single column, but this is not true. A join condition can be any boolean expression.
This may work for you:
UPDATE t
SET t.Start = t2.Start
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];

Create an event log from an excel file by turning columns into repeated rows

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.

from 15 minutes interval to hourly interval counts

am using excel sheet to display data from sql with this query
SELECT itable.Timestamp, itable.Time,
Sum(itable.CallsOffered)AS CallsOffered, Sum(itable.CallsAnswered)AS CallsAnswered, Sum(itable.CallsAnsweredAftThreshold)AS CallsAnsweredAftThreshold,
sum(CallsAnsweredDelay)AS CallsAnsweredDelay
FROM tablename itable
WHERE
(itable.Timestamp>=?) AND (itable.Timestamp<=?) AND
(itable.Application in ('1','2','3','4'))
GROUP BY itable.Timestamp, itable.Time
ORDER BY itable.Timestamp, itable.Time
and i get a data with an interval of 15 minutes like this :
Timestamp Time CallsOffered CallsAnswered CallsAnsweredAftThreshold CallsAnsweredDelay
6/1/2014 0:00 00:00 0 1 1 52
6/1/2014 0:15 00:15 3 1 1 23
6/1/2014 0:30 00:30 3 3 2 89
6/1/2014 0:45 00:45 0 0 0 0
6/1/2014 1:00 01:00 0 0 0 0
6/1/2014 1:15 01:15 4 1 1 12
6/1/2014 1:30 01:30 1 1 1 39
6/1/2014 1:45 01:45 0 0 0 0
6/1/2014 2:00 02:00 2 1 0 7
6/1/2014 2:15 02:15 1 1 1 80
6/1/2014 2:30 02:30 3 2 2 75
6/1/2014 2:45 02:45 0 0 0 0
6/1/2014 3:00 03:00 0 0 0 0
and i want to convert the interval from being 15 minutes to hourly interval
like this
2014-07-01 00:00:00.000
2014-07-01 01:00:00.000
2014-07-01 02:00:00.000
2014-07-01 03:00:00.000
2014-07-01 04:00:00.000
2014-07-01 05:00:00.000
2014-07-01 06:00:00.000
2014-07-01 07:00:00.000
2014-07-01 08:00:00.000
2014-07-01 09:00:00.000
2014-07-01 10:00:00.000
2014-07-01 11:00:00.000
2014-07-01 12:00:00.000
2014-07-01 13:00:00.000
2014-07-01 14:00:00.000
the query i came up with is :
select
timestamp = DATEADD(hour,datediff(hour,0,app.Timestamp),0),
Sum(app.CallsOffered)AS CallsOffered,
Sum(app.CallsAnswered)AS CallsAnswered,
Sum(app.CallsAnsweredAftThreshold)AS CallsAnsweredAftThreshold,
sum(CallsAnsweredDelay)AS CallsAnsweredDelay,
max(MaxCallsAnsDelay) as MaxCallsAnsDelay ,
max(app.MaxCallsAbandonedDelay)as MaxCallsAbandonedDelay
from tablename app
where Timestamp >='2014-7-1' AND timestamp<='2014-7-2' and
(app.Application in (
'1',
'2',
'3',
'4')
group by DATEADD(hour,datediff(hour,0,Timestamp),0)
order by Timestamp;
i get the result i want when i run in in Microsoft Sql server Managment studio
but it gives me a long error when i try running the same query in Microsoft Query in excel the error is like i cant start with timestamp
and that its giving me error for DATEADD ,DATEDIFF
so is there something i should change in my query or anything i can do to get an hourly count interval instead of 15 minutes count interval as ive shown
and thank you in advance