WITH config AS (
SELECT '2024-07-05'::timestamp AS sdate, '2024-07-09'::timestamp + '1
day'::interval AS edate
),
total_hours AS (
SELECT EXTRACT(EPOCH FROM (SELECT edate FROM config) - (SELECT sdate FROM
config)) / (3600 * 24) AS days
),
feeder_details AS (
SELECT
"CIRCLE_NAME_v" AS circle,
"FEEDER_ID_v" AS feeder_id,
"FEEDER_NAME_v" AS feeder_name,
"FEEDER_AREA_TYPE_v" AS area_type,
"FEEDER_CAT_v" AS feeder_category,
"TC_COUNT_i" AS consumer_served,
"RUNNING_HOURS_f" AS running_hours
FROM public."FEEDER_DETAILS"
WHERE "VOLTAGE_LEVEL_v" = '33'
),
ts_point1 AS (
SELECT
split_part(point_name, '~', 6) AS feeder_id_ts,
split_part(point_name, '~', 11) AS tag_id
FROM public.__ts_point_info_table
WHERE point_name LIKE '%\_STS' AND split_part(point_name, '~', 6) != ''
),
ts_point AS (
SELECT *
FROM feeder_details
LEFT JOIN ts_point1 ON feeder_id = feeder_id_ts
),
digital_tags_data AS (
SELECT
point_id,
SUM(interval_0) AS transit,
SUM(interval_1) AS open_duration,
SUM(interval_2) AS close_duration,
SUM(interval_3) AS error_state
FROM public.get_digital_tags_data('FeederLog', (SELECT sdate FROM config),
(SELECT edate FROM config), 5,
(SELECT string_agg(tag_id, ',') FROM ts_point))
GROUP BY 1
),
digital_tags_data_1 AS (
SELECT
point_id, transit, open_duration, close_duration, error_state,
(((transit + (1440 - (transit + open_duration + close_duration +
error_state))) / 1440) * 100)::numeric AS down_transit
FROM digital_tags_data
),
digital_tags_data_join AS (
SELECT
tag_id, feeder_id, feeder_name, circle, feeder_category, consumer_served,
CASE
WHEN ROUND(COALESCE(down_transit, 100)::numeric, 2) > 100 THEN 100
WHEN ROUND(COALESCE(down_transit, 100)::numeric, 2) < 0 THEN 0
ELSE ROUND(COALESCE(down_transit, 100)::numeric, 2)
END AS down_transit
FROM digital_tags_data_1
RIGHT JOIN ts_point ON tag_id = point_id
WHERE (COALESCE(down_transit, 100)) < (transit)
),
outage_details AS (
SELECT
"LOG_TIME_d" + '5 hr 30 min'::interval AS log_time,
"END_TIME_d" + '5 hr 30 min'::interval AS end_time,
"FEEDER_ID_v" AS feeder_id_ot,
"OUTAGE_DURATION_i" AS outage_duration,
"OUTAGE_FLAGS_i" AS outage_flags,
"CONSUMER_COUNT_i" AS affected_consumer,
CASE
WHEN "OUTAGE_FLAGS_i" = 0 THEN 'Planned'
ELSE 'Unplanned'
END AS outage_type
FROM public.get_outage_details((SELECT sdate - '5 hr 30min'::interval FROM
config), (SELECT edate - '5 hr 30min'::interval FROM config))
WHERE "FEEDER_ID_v" IN (SELECT feeder_id FROM digital_tags_data_join)
ORDER BY 1, 4, 3
),
outage_details1 AS (
SELECT
feeder_id_ot, outage_flags, outage_type, SUM(affected_consumer) AS
total_affected_consumer, SUM(outage_duration) AS total_outage_duration,
COUNT(outage_duration) AS total_outage_count,
(CASE WHEN outage_duration >= 5 AND outage_duration < 15 THEN
outage_duration END) AS "5_to_15_min",
(CASE WHEN outage_duration >= 15 AND outage_duration < 30 THEN
outage_duration END) AS "15_to_30_min",
(CASE WHEN outage_duration >= 30 AND outage_duration < 60 THEN
outage_duration END) AS "30_min_to_1_hr",
(CASE WHEN outage_duration >= 60 AND outage_duration < 120 THEN
outage_duration END) AS "1_to_2_hr",
(CASE WHEN outage_duration >= 120 AND outage_duration < 180 THEN
outage_duration END) AS "2_to_3_hr",
(CASE WHEN outage_duration >= 180 AND outage_duration < 240 THEN
outage_duration END) AS "3_to_4_hr",
(CASE WHEN outage_duration >= 240 AND outage_duration < 300 THEN
outage_duration END) AS "4_to_5_hr",
(CASE WHEN outage_duration >= 300 AND outage_duration < 360 THEN
outage_duration END) AS "5_to_6_hr",
(CASE WHEN outage_duration >= 360 AND outage_duration < 420 THEN
outage_duration END) AS "6_to_7_hr",
(CASE WHEN outage_duration >= 420 AND outage_duration < 480 THEN
outage_duration END) AS "7_to_8_hr",
(CASE WHEN outage_duration >= 480 THEN outage_duration END) AS ">_8hr"
FROM outage_details
GROUP BY 1, 2, 3, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17
),
outage_details2 AS (
SELECT
feeder_id_ot, outage_flags, outage_type, total_outage_duration,
total_affected_consumer,
COUNT("5_to_15_min") AS "5_to_15_min",
COUNT("15_to_30_min") AS "15_to_30_min",
COUNT("30_min_to_1_hr") AS "30_min_to_1_hr",
COUNT("1_to_2_hr") AS "1_to_2_hr",
COUNT("2_to_3_hr") AS "2_to_3_hr",
COUNT("3_to_4_hr") AS "3_to_4_hr",
COUNT("4_to_5_hr") AS "4_to_5_hr",
COUNT("5_to_6_hr") AS "5_to_6_hr",
COUNT("6_to_7_hr") AS "6_to_7_hr",
COUNT("7_to_8_hr") AS "7_to_8_hr",
COUNT(">_8hr") AS ">_8hr"
FROM outage_details1
GROUP BY 1, 2, 3, 4, 5
),
outage_details3 AS (
SELECT b.circle AS circles, b.feeder_id, b.feeder_category,
MAX(b.consumer_served) AS total_consumer, b.down_transit, a.*
FROM outage_details2 a
LEFT JOIN digital_tags_data_join b ON feeder_id_ot = feeder_id
GROUP BY 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21
),
feeder_count AS (
SELECT
circle,
COUNT(feeder_id) AS total_feeder_count
FROM feeder_details
GROUP BY circle
),
feeder_min_outage AS (
SELECT
circles,
COUNT(DISTINCT feeder_id) AS feeders_with_min_outage
FROM outage_details3
WHERE
"5_to_15_min" IS NOT NULL
OR "15_to_30_min" IS NOT NULL
OR "30_min_to_1_hr" IS NOT NULL
OR "1_to_2_hr" IS NOT NULL
OR "2_to_3_hr" IS NOT NULL
OR "3_to_4_hr" IS NOT NULL
OR "4_to_5_hr" IS NOT NULL
OR "5_to_6_hr" IS NOT NULL
OR "6_to_7_hr" IS NOT NULL
OR "7_to_8_hr" IS NOT NULL
OR ">_8hr" IS NOT NULL
GROUP BY circles
)
SELECT
fmo.circles,
fc.total_feeder_count,
fmo.feeders_with_min_outage,
SUM(od3.total_outage_duration) AS total_outage_duration,
COUNT(DISTINCT od3.feeder_id) AS total_outage_count,
ROUND((SUM(od3.total_outage_duration) / fc.total_feeder_count)::numeric, 2) AS
avg_outage_duration,
ROUND(AVG(od3.down_transit)::numeric, 2) AS avg_down_transit,
ROUND(
(
((MAX(fd.running_hours) * (SELECT days FROM total_hours) * 60) -
SUM(od3.total_outage_duration)::numeric)
/ (SELECT days FROM total_hours)
)::numeric, 2
) AS avg_supply_in_day
FROM
feeder_min_outage fmo
LEFT JOIN
feeder_count fc ON fmo.circles = fc.circle
LEFT JOIN
outage_details3 od3 ON fmo.circles = od3.circles
LEFT JOIN
feeder_details fd ON od3.feeder_id = fd.feeder_id
GROUP BY
fmo.circles, fc.total_feeder_count, fmo.feeders_with_min_outage
ORDER BY
fmo.circles;