Compare commits

...

1 Commits

Author SHA1 Message Date
6c15ce77fe bug fix 2025-05-22 16:09:12 +03:00
2 changed files with 32 additions and 32 deletions

View File

@ -109,7 +109,8 @@ select space_id,
FROM final_data FROM final_data
ON CONFLICT (space_uuid, event_date) DO UPDATE ON CONFLICT (space_uuid, event_date) DO UPDATE
SET SET
occupancy_percentage = EXCLUDED.occupancy_percentage; occupancy_percentage = EXCLUDED.occupancy_percentage,
occupied_seconds = EXCLUDED.occupied_seconds;

View File

@ -18,10 +18,9 @@ WITH params AS (
ON p.uuid = d.product_device_uuid ON p.uuid = d.product_device_uuid
WHERE p.cat_name = 'hps' WHERE p.cat_name = 'hps'
AND l.code = 'presence_state' AND l.code = 'presence_state'
), )
-- Step 2: Identify periods when device reports "none" , device_none_periods AS (
device_none_periods AS (
SELECT SELECT
space_id, space_id,
device_id, device_id,
@ -29,20 +28,18 @@ device_none_periods AS (
LEAD(event_time) OVER (PARTITION BY device_id ORDER BY event_time) AS empty_until LEAD(event_time) OVER (PARTITION BY device_id ORDER BY event_time) AS empty_until
FROM start_date FROM start_date
WHERE value = 'none' WHERE value = 'none'
), )
-- Step 3: Clip the "none" periods to the edges of each day , clipped_device_none_periods AS (
clipped_device_none_periods AS (
SELECT SELECT
space_id, space_id,
GREATEST(empty_from, DATE_TRUNC('day', empty_from)) AS clipped_from, GREATEST(empty_from, DATE_TRUNC('day', empty_from)) AS clipped_from,
LEAST(empty_until, DATE_TRUNC('day', empty_until) + INTERVAL '1 day') AS clipped_until LEAST(empty_until, DATE_TRUNC('day', empty_until) + INTERVAL '1 day') AS clipped_until
FROM device_none_periods FROM device_none_periods
WHERE empty_until IS NOT NULL WHERE empty_until IS NOT NULL
), )
-- Step 4: Break multi-day periods into daily intervals , generated_daily_intervals AS (
generated_daily_intervals AS (
SELECT SELECT
space_id, space_id,
gs::date AS day, gs::date AS day,
@ -50,10 +47,9 @@ generated_daily_intervals AS (
LEAST(clipped_until, gs + INTERVAL '1 day') AS interval_end LEAST(clipped_until, gs + INTERVAL '1 day') AS interval_end
FROM clipped_device_none_periods, FROM clipped_device_none_periods,
LATERAL generate_series(DATE_TRUNC('day', clipped_from), DATE_TRUNC('day', clipped_until), INTERVAL '1 day') AS gs LATERAL generate_series(DATE_TRUNC('day', clipped_from), DATE_TRUNC('day', clipped_until), INTERVAL '1 day') AS gs
), )
-- Step 5: Merge overlapping or adjacent intervals per day , merged_intervals AS (
merged_intervals AS (
SELECT SELECT
space_id, space_id,
day, day,
@ -69,20 +65,18 @@ merged_intervals AS (
FROM generated_daily_intervals FROM generated_daily_intervals
) sub ) sub
WHERE prev_end IS NULL OR interval_start > prev_end WHERE prev_end IS NULL OR interval_start > prev_end
), )
-- Step 6: Sum up total missing seconds (device reported "none") per day , missing_seconds_per_day AS (
missing_seconds_per_day AS (
SELECT SELECT
space_id, space_id,
day AS missing_date, day AS missing_date,
SUM(EXTRACT(EPOCH FROM (interval_end - interval_start))) AS total_missing_seconds SUM(EXTRACT(EPOCH FROM (interval_end - interval_start))) AS total_missing_seconds
FROM merged_intervals FROM merged_intervals
GROUP BY space_id, day GROUP BY space_id, day
), )
-- Step 7: Calculate total occupied time per day (86400 - missing) , occupied_seconds_per_day AS (
occupied_seconds_per_day AS (
SELECT SELECT
space_id, space_id,
missing_date as event_date, missing_date as event_date,
@ -91,27 +85,32 @@ occupied_seconds_per_day AS (
FROM missing_seconds_per_day FROM missing_seconds_per_day
) )
-- Final Output
, final_data as ( , final_data as (
SELECT occupied_seconds_per_day.space_id, SELECT
occupied_seconds_per_day.event_date, occupied_seconds_per_day.space_id,
occupied_seconds_per_day.occupancy_percentage occupied_seconds_per_day.event_date,
FROM occupied_seconds_per_day total_occupied_seconds,
join params p on true occupancy_percentage
and p.space_id = occupied_seconds_per_day.space_id FROM occupied_seconds_per_day
and p.event_date = occupied_seconds_per_day.event_date JOIN params p
ORDER BY 1,2 ON p.space_id = occupied_seconds_per_day.space_id
AND p.event_date = occupied_seconds_per_day.event_date
) )
INSERT INTO public."space-daily-occupancy-duration" ( INSERT INTO public."space-daily-occupancy-duration" (
space_uuid, space_uuid,
event_date, event_date,
occupied_seconds,
occupancy_percentage occupancy_percentage
) )
select space_id, SELECT
event_date, space_id,
occupancy_percentage event_date,
total_occupied_seconds,
occupancy_percentage
FROM final_data FROM final_data
ON CONFLICT (space_uuid, event_date) DO UPDATE ON CONFLICT (space_uuid, event_date) DO UPDATE
SET SET
occupancy_percentage = EXCLUDED.occupancy_percentage; occupied_seconds = EXCLUDED.occupied_seconds,
occupancy_percentage = EXCLUDED.occupancy_percentage;