129 lines
3.5 KiB
SQL
129 lines
3.5 KiB
SQL
WITH base AS (
|
|
SELECT
|
|
t_stamp,
|
|
Name,
|
|
Full,
|
|
Half_Full,
|
|
Jam,
|
|
No_Container,
|
|
Block_Operation
|
|
FROM lane_data
|
|
WHERE t_stamp BETWEEN :startTime AND :endTime
|
|
),
|
|
|
|
-- Unpivot signals into rows
|
|
ev AS (
|
|
SELECT Name, t_stamp, 'Full' AS sig, Full AS val FROM base
|
|
UNION ALL SELECT Name, t_stamp, 'Half_Full', Half_Full FROM base
|
|
UNION ALL SELECT Name, t_stamp, 'Jam', Jam FROM base
|
|
UNION ALL SELECT Name, t_stamp, 'No_Container', No_Container FROM base
|
|
UNION ALL SELECT Name, t_stamp, 'Block_Operation', Block_Operation FROM base
|
|
),
|
|
|
|
-- Add previous and next values, and find falling edges
|
|
ch AS (
|
|
SELECT
|
|
Name,
|
|
sig,
|
|
t_stamp,
|
|
val,
|
|
LAG(val) OVER (PARTITION BY Name, sig ORDER BY t_stamp) AS prev_val,
|
|
LEAD(val) OVER (PARTITION BY Name, sig ORDER BY t_stamp) AS next_val,
|
|
LEAD(t_stamp) OVER (PARTITION BY Name, sig ORDER BY t_stamp) AS next_ts
|
|
FROM ev
|
|
),
|
|
|
|
-- Mark rising and falling edges
|
|
edges AS (
|
|
SELECT
|
|
Name,
|
|
sig,
|
|
t_stamp,
|
|
val,
|
|
CASE
|
|
WHEN val = 1 AND (prev_val = 0 OR prev_val IS NULL) THEN 1 -- rising edge
|
|
ELSE 0
|
|
END AS is_rising,
|
|
CASE
|
|
WHEN val = 0 AND prev_val = 1 THEN 1 -- falling edge
|
|
ELSE 0
|
|
END AS is_falling
|
|
FROM ch
|
|
),
|
|
|
|
-- Find interval starts (rising edges)
|
|
starts AS (
|
|
SELECT
|
|
Name,
|
|
sig,
|
|
t_stamp AS start_ts
|
|
FROM edges
|
|
WHERE is_rising = 1
|
|
),
|
|
|
|
-- Find interval ends (falling edges)
|
|
ends AS (
|
|
SELECT
|
|
Name,
|
|
sig,
|
|
t_stamp AS end_ts
|
|
FROM edges
|
|
WHERE is_falling = 1
|
|
),
|
|
|
|
-- Match each start with the next falling edge (or endTime if none exists)
|
|
intervals AS (
|
|
SELECT
|
|
s.Name,
|
|
s.sig,
|
|
s.start_ts,
|
|
COALESCE(
|
|
(SELECT MIN(e.end_ts)
|
|
FROM ends e
|
|
WHERE e.Name = s.Name
|
|
AND e.sig = s.sig
|
|
AND e.end_ts > s.start_ts),
|
|
:endTime
|
|
) AS end_ts
|
|
FROM starts s
|
|
),
|
|
|
|
-- Sum durations
|
|
dur AS (
|
|
SELECT
|
|
Name,
|
|
SUM(CASE WHEN sig = 'Full' THEN TIMESTAMPDIFF(SECOND, start_ts, end_ts) ELSE 0 END) AS Full_Duration_Sec,
|
|
SUM(CASE WHEN sig = 'Half_Full' THEN TIMESTAMPDIFF(SECOND, start_ts, end_ts) ELSE 0 END) AS Half_Full_Duration_Sec,
|
|
SUM(CASE WHEN sig = 'Jam' THEN TIMESTAMPDIFF(SECOND, start_ts, end_ts) ELSE 0 END) AS Jam_Duration_Sec,
|
|
SUM(CASE WHEN sig = 'No_Container' THEN TIMESTAMPDIFF(SECOND, start_ts, end_ts) ELSE 0 END) AS No_Container_Duration_Sec,
|
|
SUM(CASE WHEN sig = 'Block_Operation' THEN TIMESTAMPDIFF(SECOND, start_ts, end_ts) ELSE 0 END) AS Block_Operation_Duration_Sec
|
|
FROM intervals
|
|
GROUP BY Name
|
|
)
|
|
|
|
SELECT
|
|
:startTime AS `Start Time`,
|
|
:endTime AS `End Time`,
|
|
d.Name AS `Lane ID`,
|
|
CASE
|
|
WHEN d.Name LIKE 'S01%' THEN 'S01'
|
|
WHEN d.Name LIKE 'S02%' THEN 'S02'
|
|
ELSE 'N/A'
|
|
END AS `Sorter`,
|
|
COALESCE(Full_Duration_Sec, 0) AS `Full Duration Sec`,
|
|
COALESCE(Half_Full_Duration_Sec, 0) AS `Half Full Duration Sec`,
|
|
COALESCE(Jam_Duration_Sec, 0) AS `Jam Duration Sec`,
|
|
COALESCE(No_Container_Duration_Sec, 0) AS `No Container Duration Sec`,
|
|
COALESCE(Block_Operation_Duration_Sec, 0) AS `Block Operation Duration Sec`
|
|
FROM dur d
|
|
|
|
UNION ALL
|
|
|
|
SELECT
|
|
:startTime, :endTime,
|
|
'N/A', 'N/A',
|
|
0,0,0,0,0
|
|
WHERE NOT EXISTS (SELECT 1 FROM dur)
|
|
|
|
ORDER BY `Lane ID`;
|