Home > front end >  How do I aggregate from multiple rows
How do I aggregate from multiple rows

Time:07-24

I have the below table:

Person_ID   | Timestamp           | Action
1           | 01-01-2020 00:01:00 | LOGGED ON
1           | 01-01-2020 00:02:00 | ON BREAK
1           | 01-01-2020 00:02:30 | OFF BREAK
1           | 01-01-2020 00:04:00 | LOGGED OFF
1           | 01-01-2020 00:04:30 | LOGGED ON
1           | 01-01-2020 00:05:30 | ON BREAK
1           | 01-01-2020 00:06:00 | OFF BREAK
1           | 01-01-2020 00:08:00 | LOGGED OFF
2           | 01-02-2020 00:04:00 | LOGGED ON
2           | 01-02-2020 00:10:00 | LOGGED OFF

My goal is to write an SQL view to get the below result:

Person_ID   | LoggedInTime_hours | OnBreakTime_hours
1           | 6.5                | 1 
2           | 6                  | 0 

For each Person_ID, calculate the difference in hours between each pair of occurrences of LOGGED IN/LOGGED OUT and ON BREAK/OFF BREAK respectively.

Thanks a lot for your expertise and help.

CodePudding user response:

1st of all LoggedInTime_hours for PERSON_ID = 1 should be 5.5 hours not 6.5 hours.

Let us assume the table name is TEST.

Database : MySQL

SELECT
PERSON_ID,
IFNULL(SUM(CASE WHEN PREV_ACTIVE_IND - ACTIVE_IND > 0 THEN TIMESTAMPDIFF(SECOND, PREV_TIMESTAMP, TIMESTAMP)/3600 END),0) LoggedInTime_hours,
IFNULL(SUM(CASE WHEN PREV_ACTIVE_IND - ACTIVE_IND = 0 THEN TIMESTAMPDIFF(SECOND, PREV_TIMESTAMP, TIMESTAMP)/3600 END),0) OnBreakTime_hours
FROM
(SELECT
PERSON_ID,
PREV_ACTION,
ACTION,
CASE WHEN PREV_ACTION = 'LOGGED OFF' THEN 1 
WHEN PREV_ACTION LIKE '%BREAK' THEN 2 
WHEN PREV_ACTION IS NULL THEN NULL 
ELSE 3 
END AS PREV_ACTIVE_IND,
CASE WHEN ACTION = 'LOGGED OFF' THEN 1
WHEN ACTION LIKE '%BREAK' THEN 2
WHEN ACTION IS NULL THEN NULL
ELSE 3 
END AS ACTIVE_IND,
PREV_TIMESTAMP,
TIMESTAMP
FROM
(SELECT PERSON_ID,
TIMESTAMP,
LAG(TIMESTAMP,1) OVER (PARTITION BY PERSON_ID) PREV_TIMESTAMP,
LAG(ACTION,1) OVER (PARTITION BY PERSON_ID) PREV_ACTION,
ACTION
FROM TEST) T) T2
GROUP BY PERSON_ID

Hope this query will help.

CodePudding user response:

Try the following query using MySQL v8.0:

With CTE As
(
  Select Person_ID, Action_,
  TIME_TO_SEC(TIMEDIFF(Lead(Timestamp_) Over (Partition By Person_ID Order By Timestamp_), Timestamp_))/60 As DIFF
  From MyData Where Action_ In ('LOGGED ON','LOGGED OFF')
  Union All
  Select Person_ID,Action_,
  TIME_TO_SEC(TIMEDIFF(Lead(Timestamp_) Over (Partition By Person_ID Order By Timestamp_), Timestamp_))/60 As DIFF
  From MyData Where Action_ In ('ON BREAK','OFF BREAK')
)

Select Person_ID, 
Sum(Case When Action_='LOGGED ON' Then DIFF Else 0 End) As LoggedInTime_hours,
Sum(Case When Action_='ON BREAK' Then DIFF Else 0 End) As OnBreakTime_hours 
From CTE
Group By Person_ID

See a demo from db-fiddle.

  • Related