Oracle selecting one row from multiple rows based on a column value - sql

I am using Oracle SQL.
Here is the example table:
MachineStatus
--------------
Machine Status date_time station
G1 1 07/09/2014 10:11 s1
G2 1 07/09/2014 10:11 s1
G3 0 07/09/2014 10:11 s1
G1 1 07/09/2014 10:12 s1
G2 1 07/09/2014 10:12 s1
G3 0 07/09/2014 10:12 s1
G1 0 07/09/2014 10:13 s1
G2 0 07/09/2014 10:13 s1
G3 0 07/09/2014 10:13 s1
I want to list the status of the station on any given minute as available if any of the machines is available(if status is 1) as below.
Station status date_time
s1 1 07/09/2014 10:11
s1 1 07/09/2014 10:12
s1 0 07/09/2014 10:13
A report needs to be generated on a daily/weekly basis based on the availability.
How should I approach this query?

The following query will give you the result from your example:
SELECT
station,
(CASE WHEN sum(status) > 1 THEN 1 ELSE 0 END) AS status,
date_time
FROM MachineStatus
GROUP BY station, date_time
ORDER BY date_time
Having at least one status that is 1 means that the sum of statuses for that group and date_time must be greater than 1.

Related

SQL: Find discontinuities in temporal data

I have a dataset where I have to find gaps in the temporal columns and show what happened before and after each section for each person in the list.
If nothing was present in the day before valid_from, I want a 0, and if something was present, I want whatever was present.
If nothing was present the day after valid_to, I want a 0.
See the example below, where person XXX starts in G1 and moves to G2 with only 1 day between. Hence old_value = 0 and new_value is G1 followed by old_value = G1 and new_value = G2.
It should never happen that valid_to next valid_from for the same person_id
Input data:
id
person_id
current_value
valid_from
valid_to
1
XXX
G1
2022-01-01
2022-02-01
2
XXX
G2
2022-02-02
2022-03-01
3
YYY
G1
2022-01-01
2022-02-01
4
YYY
G3
2022-02-02
2022-03-01
5
YYY
G1
2022-04-01
2022-04-30
6
ZZZ
G2
2022-01-01
2022-01-31
Expected result:
person_id
old_value
new_value
valid_from
XXX
0
G1
2022-01-01
XXX
G1
G2
2022-02-02
XXX
G2
0
2022-03-02
YYY
0
G1
2022-01-01
YYY
G1
G3
2022-02-02
YYY
G3
0
2022-02-03
YYY
0
G1
2022-04-01
YYY
G1
0
2022-05-01
ZZZ
0
G2
2022-01-01
ZZZ
G2
0
2022-02-01
What have been tried so far: Self joins and various filters, but that does not catch the case with ZZZ.
Also tried some magic with LAG in an inner query, but no success.

Is there way to find a value / Text in a particular column of a SQL table?

I am relatively new to SQL, I have requirement like below.
I have the following tables.
Table Name: Name
ID
Name
1
AAA
2
BBB
3
CCC
4
DDD
5
EEE
Table Name: Sprint
Sprint Event
ID
Time
LAP
LIVE Status
Final Status
A1
1
2018-11-02 15:28:11
0
Started
Started
A1
1
2018-11-02 15:28:12
0
Running
Running
A1
1
2018-11-02 15:28:12
1
Running
Running
A1
1
2018-11-02 15:28:15
2
Running
Running
A1
1
2018-11-02 15:28:16
3
Running
Started
A1
1
2018-11-02 15:32:16
4
Completed
Success
A1
2
2018-11-02 15:28:16
0
Running
Running
A1
2
2018-11-02 15:28:17
1
Running
Running
A1
2
2018-11-02 15:28:19
2
Running
Started
A1
2
2018-11-02 15:36:19
3
Running
Running
A1
2
2018-11-02 15:36:19
4
Completed
Success
B1
3
2020-06-04 16:14:23
0
Started
Started
B1
3
2020-06-04 16:14:23
0
Running
Running
B1
3
2020-06-04 16:14:23
1
Running
Running
B1
3
2020-06-04 16:14:27
2
Running
Running
B1
3
2020-06-04 16:16:27
3
Completed
Success
B1
4
2020-06-04 16:18:27
0
Running
Running
B1
4
2020-06-04 16:14:27
1
Running
Running
B1
4
2020-06-04 16:14:27
2
ERROR
Running
B1
4
2020-06-04 16:14:29
3
Running
Started
B1
4
2020-06-04 16:14:29
4
Running
Running
B1
4
2020-06-04 16:23:30
5
Completed
Success
I also have multiple Sprint IDs like A1, B1, B2, C2 and so on.,
Table Name: State
ID
State
1
NY
2
TX
3
AL
4
FL
5
IL
Looking for result like this
Sprint
Name
State
Laps (Count)
StartTime
EndTime
Status
Elapsed Time (Mins)
A1
AAA
NY
6
2018-11-02 15:28:11
2018-11-02 15:32:16
Success
4
A1
BBB
TX
5
2018-11-02 15:28:16
2018-11-02 15:36:19
Success
8
B1
CCC
AL
5
2020-06-04 16:14:23
2020-06-04 16:16:27
Success
2
B2
DDD
FL
6
2020-06-04 16:14:27
2020-06-04 16:23:30
Failed
9
I am trying to query the sprint table for each ID's start time, end time and status. Status should be based on that particular's IDs last record's Final status value. If the last record's Final status value is Success for specific ID from start time to end time, I need to print Success. If any ID has any ERROR in LIVE status, regardless of their final status last record's value, I need to print Failure.
Here is the code which I tried
SELECT
N.Name,
st.state,
Count (s1.Lap) as LapCount,
MIN(s1.Time) AS [StartTime],
MAX(s1.Time) AS [EndTime],
case
when (count (s2.lap) < 380 ) then 'Failed'
else 'Succeeded'
END AS Status
datediff(MINUTE, min(s1.Time), max(s1.Time)) as 'RunTime in Mins'
FROM Sprint s1, Sprint s2
FULL outer join Name N on N.ID=s2.ID
FULL outer join State st on st.ID=s2.ID
WHERE s1.ID = s2.ID
AND s2.Time = (SELECT
MAX(Time)
FROM Sprint s3
WHERE s2.ID = s3.ID) and
s1.Sprint='A1'
GROUP BY N.Name,st.state
The issue with this, I am not able look for ERROR in Live Status column and print Failure. Also, I need to query multiple Sprint IDs and my where condition will be like where s1.Sprint='A1' and s1.Sprint='B1'.
You still is not paying much attention to your sample data, anyway:
WITH SpintSummary AS (SELECT SprintEvent, ID, MIN(Time) AS StartTime, MAX(Time) AS EndTime, COUNT(LAP) AS Laps
FROM Sprint
GROUP BY SprintEvent, ID)
SELECT ss.SprintEvent, n.Name, s.State, ss.Laps, ss.StartTime, ss.EndTime,
CASE
WHEN e.cnt=0 THEN f.Status
ELSE 'Failed'
END AS Status,
DATEDIFF(MINUTE, ss.StartTime, ss.EndTime) AS ElapsedTimeMins
FROM SpintSummary ss
INNER JOIN dbo.Name n ON n.Id=ss.ID
INNER JOIN dbo.State s ON s.Id=ss.ID
CROSS APPLY(SELECT COUNT(*)
FROM Sprint sp
WHERE sp.SprintEvent=ss.SprintEvent AND sp.ID=ss.ID AND sp.LIVEStatus='ERROR') e(cnt)
CROSS APPLY(SELECT TOP(1)FinalStatus
FROM Sprint sp
WHERE sp.SprintEvent=ss.SprintEvent AND sp.ID=ss.ID
ORDER BY sp.Time DESC, LAP DESC) f(Status);
Here is DBFiddle demo
Next time, please try to supply sample data as is in the fiddle.

Exclude Sub Intervals from parent interval in postgresql

I have 2 tables:
Table 1 has Users Session Data
user_id
login_time
logout_time
a1
2022-01-10 09:02:54.927
2022-01-10 18:07:42.876
s1
2022-01-10 09:07:51.104
2022-01-10 18:44:23.053
Table 2 has Users Chat Data
user_id
user_connected_time
user_disconnected_time
a1
2022-02-10 13:10:49.975
2022-02-10 13:25:22.26
a1
2022-02-10 17:35:12.34
2022-02-10 17:55:05.283
s1
2022-02-15 14:08:34.39
2022-02-15 14:09:28.627
s1
2022-02-15 14:00:47.261
2022-02-15 14:16:29.339
I need the agent ideal time i.e. when the agent wasn't connected on any chat.
Expected output
Agent Ideal Duration
agent_ideal_duration
agent_id
08:44:55.006
a1
09:20:49.871
s1
Overlapping chat duration is removed from Agent's s1 ideal time.
Note: 1 agent can take multiple chats at a time.

SQL Query for getting data from different columns of different rows

I have a dataset as following:
VN FNAME SEG STARTTIME ENDTIME F1 DIS F2
5 try 1 09-DEC-21 10.00.00 PM 09-DEC-21 11.05.00 PM 0 2 1
1 eat 1 09-DEC-21 11.00.00 PM 09-DEC-21 11.59.59 PM 1 15 1
5 sit 1 09-DEC-21 11.30.00 PM 09-DEC-21 11.59.59 PM 0 21 1
1 eat 2 10-DEC-21 12.00.00 AM 10-DEC-21 02.00.00 AM 1 15 1
5 sit 2 10-DEC-21 12.00.00 AM 10-DEC-21 04.00.00 AM 0 21 1
9 fly 1 10-DEC-21 01.00.00 AM 10-DEC-21 04.30.00 AM 1 50 1
4 say 1 10-DEC-21 05.00.00 AM 10-DEC-21 06.30.00 AM 0 25 1
With the above dataset I want to fetch records with unique FNAME where F1 and F2 both are 1 but STARTTIME displays the STARTTIME where SEG = 1 and ENDTIME displays the ENDTIME where SEG = max(SEG) for the FNAME. So basically the result which I am looking at is:
VN FNAME STARTTIME ENDTIME DIS
1 eat 09-DEC-21 11.00.00 PM 10-DEC-21 02.00.00 AM 15
9 fly 10-DEC-21 01.00.00 AM 10-DEC-21 04.30.00 AM 50
How can I achieve this using a SQL query? The database I am working with is Oracle.
Any help appreciated. Many thanks in advance.
Something like so, using grouing and subqueries. Having count(*) as 1 will show where there is 1 instance of the name, with F1 & F2 being 1.
select t.fname,
(select t2.starttime from table1 as t2 where t2.fname=t.fname and t2.seg=1) as start_time,
max(t.endtime) as end_time
from table1 as t
where t.f1=1 and t.f2=1
group by t.fname
having count(*)=1

SQL/Presto: how to rank within a subgroup of each group

I have a table like the following:
group_id sub_group_id user_id score time
1 a1 ann 1 2019
1 a1 bob 1 2020
1 a2 cat 0 2020
2 b1 dan 0 2019
2 b1 eva 0 2019
2 b1 ed 1 2020
2 b2 liz 1 2020
i want to rank user_id within subgroup of each group by the score and then by time (earlier better) each user_id gets. so the desired output is
group_id sub_group_id user_id score time rank
1 a1 ann 1 2019 1
1 a1 bob 1 2020 2
1 a2 cat 0 2020 1
2 b1 dan 0 2019 1
2 b1 eva 0 2019 1
2 b1 ed 1 2020 2
2 b2 liz 1 2020 1
Use rank():
select t.*,
rank() over (partition by group_id, sub_group_id order by score desc, time) as ranking
from t;
Actually, I'm not sure if higher scores are better than lower ones, so you might want score asc.