这是配网设备故障类型表:https://omhost.net/misc2025/ftu-fault-types
请忽视设备故障、环境因素两大类型。重点考虑短路故障、接地故障、失压故障、过载故障、断路故障这5大类型,以及它们的二级分类。共有5个大类,每个大类有5个子类,总共25个二级分类。
这是遥测数仓表结构定义:https://omhost.net/notes2025/telemetry-sql-tables 数仓工具是timescaledb,支持time_bucket等时序函数。
需求:针对上述25个二级分类的故障类型,分析它们的故障表现,并根据遥测数据表,将故障表现转换为sql。比如:接地故障一般就是零序电流过高,那么对应的sql就是查零序电流阈值是否超标。
应用场景:一旦有ftu的数据入库,我能立刻知道,这个数据是否正常。如果异常,对应的是什么故障分类。
三相短路
SELECT fr.FTUKey, d.FTU_ID, fr.ReadingTimestamp
FROM FactPowerReadings fr
JOIN DimFTU d ON fr.FTUKey = d.FTUKey
WHERE
(fr.IA_Current > 2 * AVG(fr.IA_Current) OVER (
PARTITION BY fr.FTUKey
ORDER BY fr.ReadingTimestamp
RANGE BETWEEN INTERVAL '1 hour' PRECEDING AND INTERVAL '1 minute' PRECEDING
)) AND
(fr.IB_Current > 2 * AVG(fr.IB_Current) OVER (
PARTITION BY fr.FTUKey
ORDER BY fr.ReadingTimestamp
RANGE BETWEEN INTERVAL '1 hour' PRECEDING AND INTERVAL '1 minute' PRECEDING
)) AND
(fr.IC_Current > 2 * AVG(fr.IC_Current) OVER (
PARTITION BY fr.FTUKey
ORDER BY fr.ReadingTimestamp
RANGE BETWEEN INTERVAL '1 hour' PRECEDING AND INTERVAL '1 minute' PRECEDING
)) AND
(fr.UAB_Voltage < 0.1 * AVG(fr.UAB_Voltage) OVER (
PARTITION BY fr.FTUKey
ORDER BY fr.ReadingTimestamp
RANGE BETWEEN INTERVAL '1 hour' PRECEDING AND INTERVAL '1 minute' PRECEDING
)) AND
(fr.UBC_Voltage < 0.1 * AVG(fr.UBC_Voltage) OVER (
PARTITION BY fr.FTUKey
ORDER BY fr.ReadingTimestamp
RANGE BETWEEN INTERVAL '1 hour' PRECEDING AND INTERVAL '1 minute' PRECEDING
)) AND
(fr.UCA_Voltage < 0.1 * AVG(fr.UCA_Voltage) OVER (
PARTITION BY fr.FTUKey
ORDER BY fr.ReadingTimestamp
RANGE BETWEEN INTERVAL '1 hour' PRECEDING AND INTERVAL '1 minute' PRECEDING
));
两相短路
SELECT fr.FTUKey, d.FTU_ID, fr.ReadingTimestamp,
CASE
WHEN fr.IA_Current > threshold_a AND fr.IB_Current > threshold_b THEN 'A-B相短路'
WHEN fr.IB_Current > threshold_b AND fr.IC_Current > threshold_c THEN 'B-C相短路'
WHEN fr.IC_Current > threshold_c AND fr.IA_Current > threshold_a THEN 'C-A相短路'
END AS fault_type
FROM FactPowerReadings fr
JOIN DimFTU d ON fr.FTUKey = d.FTUKey
CROSS JOIN (
SELECT
2 * PERCENTILE_CONT(0.95) WITHIN GROUP(ORDER BY IA_Current) AS threshold_a,
2 * PERCENTILE_CONT(0.95) WITHIN GROUP(ORDER BY IB_Current) AS threshold_b,
2 * PERCENTILE_CONT(0.95) WITHIN GROUP(ORDER BY IC_Current) AS threshold_c
FROM FactPowerReadings
WHERE ReadingTimestamp > NOW() - INTERVAL '24 hours'
) thresholds
WHERE (
(fr.IA_Current > thresholds.threshold_a AND fr.IB_Current > thresholds.threshold_b AND fr.UAB_Voltage < 0.7 *
AVG(fr.UAB_Voltage) OVER (
PARTITION BY fr.FTUKey
ORDER BY fr.ReadingTimestamp
RANGE BETWEEN INTERVAL '1 hour' PRECEDING AND INTERVAL '1 minute' PRECEDING
)
) OR
(fr.IB_Current > thresholds.threshold_b AND fr.IC_Current > thresholds.threshold_c AND fr.UBC_Voltage < 0.7 *
AVG(fr.UBC_Voltage) OVER (
PARTITION BY fr.FTUKey
ORDER BY fr.ReadingTimestamp
RANGE BETWEEN INTERVAL '1 hour' PRECEDING AND INTERVAL '1 minute' PRECEDING
)
) OR
(fr.IC_Current > thresholds.threshold_c AND fr.IA_Current > thresholds.threshold_a AND fr.UCA_Voltage < 0.7 *
AVG(fr.UCA_Voltage) OVER (
PARTITION BY fr.FTUKey
ORDER BY fr.ReadingTimestamp
RANGE BETWEEN INTERVAL '1 hour' PRECEDING AND INTERVAL '1 minute' PRECEDING
)
)
);
相间短路
WITH baseline AS (
SELECT
FTUKey,
AVG(IA_Current) AS avg_ia,
AVG(IB_Current) AS avg_ib,
AVG(IC_Current) AS avg_ic,
AVG(UAB_Voltage) AS avg_uab,
AVG(UBC_Voltage) AS avg_ubc,
AVG(UCA_Voltage) AS avg_uca
FROM FactPowerReadings
WHERE ReadingTimestamp BETWEEN NOW() - INTERVAL '1 day' AND NOW() - INTERVAL '1 hour'
GROUP BY FTUKey
)
SELECT
fr.FTUKey,
d.FTU_ID,
time_bucket('1 minute', fr.ReadingTimestamp) AS event_time,
CASE
WHEN fr.IA_Current > 1.5 * b.avg_ia AND fr.IB_Current > 1.5 * b.avg_ib AND fr.UAB_Voltage < 0.8 * b.avg_uab THEN 'A-B相间短路'
WHEN fr.IB_Current > 1.5 * b.avg_ib AND fr.IC_Current > 1.5 * b.avg_ic AND fr.UBC_Voltage < 0.8 * b.avg_ubc THEN 'B-C相间短路'
WHEN fr.IC_Current > 1.5 * b.avg_ic AND fr.IA_Current > 1.5 * b.avg_ia AND fr.UCA_Voltage < 0.8 * b.avg_uca THEN 'C-A相间短路'
END AS fault_type
FROM FactPowerReadings fr
JOIN DimFTU d ON fr.FTUKey = d.FTUKey
JOIN baseline b ON fr.FTUKey = b.FTUKey
WHERE
((fr.IA_Current > 1.5 * b.avg_ia AND fr.IB_Current > 1.5 * b.avg_ib AND fr.UAB_Voltage < 0.8 * b.avg_uab) OR
(fr.IB_Current > 1.5 * b.avg_ib AND fr.IC_Current > 1.5 * b.avg_ic AND fr.UBC_Voltage < 0.8 * b.avg_ubc) OR
(fr.IC_Current > 1.5 * b.avg_ic AND fr.IA_Current > 1.5 * b.avg_ia AND fr.UCA_Voltage < 0.8 * b.avg_uca))
AND fr.ReadingTimestamp > NOW() - INTERVAL '1 hour'
GROUP BY fr.FTUKey, d.FTU_ID, time_bucket('1 minute', fr.ReadingTimestamp), fault_type;
金属性短路
WITH baseline AS (
SELECT
FTUKey,
PERCENTILE_CONT(0.95) WITHIN GROUP(ORDER BY IA_Current) AS p95_ia,
PERCENTILE_CONT(0.95) WITHIN GROUP(ORDER BY IB_Current) AS p95_ib,
PERCENTILE_CONT(0.95) WITHIN GROUP(ORDER BY IC_Current) AS p95_ic
FROM FactPowerReadings
WHERE ReadingTimestamp BETWEEN NOW() - INTERVAL '7 day' AND NOW() - INTERVAL '1 hour'
GROUP BY FTUKey
)
SELECT
fr.FTUKey,
d.FTU_ID,
fr.ReadingTimestamp,
'Metal Short Circuit' AS fault_type
FROM FactPowerReadings fr
JOIN DimFTU d ON fr.FTUKey = d.FTUKey
JOIN baseline b ON fr.FTUKey = b.FTUKey
WHERE
((fr.IA_Current > 3 * b.p95_ia) OR
(fr.IB_Current > 3 * b.p95_ib) OR
(fr.IC_Current > 3 * b.p95_ic))
AND ((fr.UAB_Voltage < 0.3 * 380) OR (fr.UBC_Voltage < 0.3 * 380) OR (fr.UCA_Voltage < 0.3 * 380))
AND fr.ReadingTimestamp > NOW() - INTERVAL '15 minutes';
电弧性短路
WITH current_variance AS (
SELECT
FTUKey,
time_bucket('1 minute', ReadingTimestamp) AS bucket_time,
VARIANCE(IA_Current) AS var_ia,
VARIANCE(IB_Current) AS var_ib,
VARIANCE(IC_Current) AS var_ic
FROM FactPowerReadings
WHERE ReadingTimestamp > NOW() - INTERVAL '1 hour'
GROUP BY FTUKey, time_bucket('1 minute', ReadingTimestamp)
),
baseline_variance AS (
SELECT
FTUKey,
AVG(var_ia) AS avg_var_ia,
AVG(var_ib) AS avg_var_ib,
AVG(var_ic) AS avg_var_ic
FROM (
SELECT
FTUKey,
time_bucket('1 minute', ReadingTimestamp) AS bucket_time,
VARIANCE(IA_Current) AS var_ia,
VARIANCE(IB_Current) AS var_ib,
VARIANCE(IC_Current) AS var_ic
FROM FactPowerReadings
WHERE ReadingTimestamp BETWEEN NOW() - INTERVAL '24 hours' AND NOW() - INTERVAL '1 hour'
GROUP BY FTUKey, time_bucket('1 minute', ReadingTimestamp)
) t
GROUP BY FTUKey
)
SELECT
cv.FTUKey,
d.FTU_ID,
cv.bucket_time AS detection_time,
'Arc Short Circuit' AS fault_type
FROM current_variance cv
JOIN DimFTU d ON cv.FTUKey = d.FTUKey
JOIN baseline_variance bv ON cv.FTUKey = bv.FTUKey
WHERE
(cv.var_ia > 5 * bv.avg_var_ia OR cv.var_ib > 5 * bv.avg_var_ib OR cv.var_ic > 5 * bv.avg_var_ic)
AND (cv.var_ia > 0.05 OR cv.var_ib > 0.05 OR cv.var_ic > 0.05);
单相接地
SELECT fr.FTUKey, d.FTU_ID, fr.ReadingTimestamp,
CASE
WHEN fr.UA_Voltage < threshold_volt THEN 'A相接地'
WHEN fr.UB_Voltage < threshold_volt THEN 'B相接地'
WHEN fr.UC_Voltage < threshold_volt THEN 'C相接地'
END AS fault_phase
FROM FactPowerReadings fr
JOIN DimFTU d ON fr.FTUKey = d.FTUKey
CROSS JOIN (
SELECT 0.7 * PERCENTILE_CONT(0.5) WITHIN GROUP(ORDER BY UA_Voltage) AS threshold_volt
FROM FactPowerReadings
WHERE ReadingTimestamp > NOW() - INTERVAL '24 hours'
) thresholds
WHERE
fr.I0_Current > 10 AND -- 零序电流阈值通常由系统设置,这里假设为10A
(fr.UA_Voltage < thresholds.threshold_volt OR
fr.UB_Voltage < thresholds.threshold_volt OR
fr.UC_Voltage < thresholds.threshold_volt)
AND fr.ReadingTimestamp > NOW() - INTERVAL '15 minutes';
低阻接地
SELECT fr.FTUKey, d.FTU_ID, fr.ReadingTimestamp,
CASE
WHEN fr.UA_Voltage < 0.3 * baseline.avg_ua THEN 'A相低阻接地'
WHEN fr.UB_Voltage < 0.3 * baseline.avg_ub THEN 'B相低阻接地'
WHEN fr.UC_Voltage < 0.3 * baseline.avg_uc THEN 'C相低阻接地'
END AS fault_type
FROM FactPowerReadings fr
JOIN DimFTU d ON fr.FTUKey = d.FTUKey
JOIN (
SELECT
FTUKey,
AVG(UA_Voltage) AS avg_ua,
AVG(UB_Voltage) AS avg_ub,
AVG(UC_Voltage) AS avg_uc
FROM FactPowerReadings
WHERE ReadingTimestamp BETWEEN NOW() - INTERVAL '1 day' AND NOW() - INTERVAL '1 hour'
GROUP BY FTUKey
) baseline ON fr.FTUKey = baseline.FTUKey
WHERE
fr.I0_Current > 50 AND -- 低阻接地零序电流阈值较高
(fr.UA_Voltage < 0.3 * baseline.avg_ua OR
fr.UB_Voltage < 0.3 * baseline.avg_ub OR
fr.UC_Voltage < 0.3 * baseline.avg_uc)
AND fr.ReadingTimestamp > NOW() - INTERVAL '15 minutes';
高阻接地
SELECT fr.FTUKey, d.FTU_ID, fr.ReadingTimestamp,
CASE
WHEN fr.UA_Voltage < 0.9 * baseline.avg_ua AND fr.UA_Voltage > 0.7 * baseline.avg_ua THEN 'A相高阻接地'
WHEN fr.UB_Voltage < 0.9 * baseline.avg_ub AND fr.UB_Voltage > 0.7 * baseline.avg_ub THEN 'B相高阻接地'
WHEN fr.UC_Voltage < 0.9 * baseline.avg_uc AND fr.UC_Voltage > 0.7 * baseline.avg_uc THEN 'C相高阻接地'
END AS fault_type
FROM FactPowerReadings fr
JOIN DimFTU d ON fr.FTUKey = d.FTUKey
JOIN (
SELECT
FTUKey,
AVG(UA_Voltage) AS avg_ua,
AVG(UB_Voltage) AS avg_ub,
AVG(UC_Voltage) AS avg_uc
FROM FactPowerReadings
WHERE ReadingTimestamp BETWEEN NOW() - INTERVAL '1 day' AND NOW() - INTERVAL '1 hour'
GROUP BY FTUKey
) baseline ON fr.FTUKey = baseline.FTUKey
WHERE
fr.I0_Current BETWEEN 5 AND 20 AND -- 高阻接地零序电流阈值较低
(
(fr.UA_Voltage < 0.9 * baseline.avg_ua AND fr.UA_Voltage > 0.7 * baseline.avg_ua) OR
(fr.UB_Voltage < 0.9 * baseline.avg_ub AND fr.UB_Voltage > 0.7 * baseline.avg_ub) OR
(fr.UC_Voltage < 0.9 * baseline.avg_uc AND fr.UC_Voltage > 0.7 * baseline.avg_uc)
)
AND fr.ReadingTimestamp > NOW() - INTERVAL '15 minutes';
间歇性接地
WITH zero_current_variance AS (
SELECT
FTUKey,
time_bucket('5 minute', ReadingTimestamp) AS bucket_time,
VARIANCE(I0_Current) AS var_i0,
MAX(I0_Current) AS max_i0,
COUNT(*) AS readings_count
FROM FactPowerReadings
WHERE ReadingTimestamp > NOW() - INTERVAL '1 hour'
GROUP BY FTUKey, time_bucket('5 minute', ReadingTimestamp)
HAVING COUNT(*) > 10 -- 确保有足够的数据点进行分析
)
SELECT
zv.FTUKey,
d.FTU_ID,
zv.bucket_time,
'Intermittent Ground Fault' AS fault_type
FROM zero_current_variance zv
JOIN DimFTU d ON zv.FTUKey = d.FTUKey
WHERE
zv.var_i0 > 25 AND -- 零序电流方差较大
zv.max_i0 > 10; -- 最大零序电流超过阈值
中性点接地系统故障
WITH voltage_imbalance AS (
SELECT
FTUKey,
ReadingTimestamp,
(ABS(UA_Voltage - UB_Voltage) + ABS(UB_Voltage - UC_Voltage) + ABS(UC_Voltage - UA_Voltage)) /
(UA_Voltage + UB_Voltage + UC_Voltage) * 100 AS imbalance_percent,
I0_Current
FROM FactPowerReadings
WHERE ReadingTimestamp > NOW() - INTERVAL '4 hours'
)
SELECT
vi.FTUKey,
d.FTU_ID,
time_bucket('15 minute', vi.ReadingTimestamp) AS detection_time,
AVG(vi.imbalance_percent) AS avg_imbalance,
AVG(vi.I0_Current) AS avg_zero_current,
'Neutral Point Ground System Fault' AS fault_type
FROM voltage_imbalance vi
JOIN DimFTU d ON vi.FTUKey = d.FTUKey
WHERE vi.imbalance_percent > 5 AND vi.I0_Current > 3
GROUP BY vi.FTUKey, d.FTU_ID, time_bucket('15 minute', vi.ReadingTimestamp)
HAVING AVG(vi.imbalance_percent) > 5;
全电压失压
SELECT fr.FTUKey, d.FTU_ID, fr.ReadingTimestamp, 'Complete Voltage Loss' AS fault_type
FROM FactPowerReadings fr
JOIN DimFTU d ON fr.FTUKey = d.FTUKey
WHERE
(fr.UAB_Voltage < 30 OR fr.UAB_Voltage IS NULL) AND
(fr.UBC_Voltage < 30 OR fr.UBC_Voltage IS NULL) AND
(fr.UCA_Voltage < 30 OR fr.UCA_Voltage IS NULL) AND
fr.ReadingTimestamp > NOW() - INTERVAL '15 minutes';
部分失压
SELECT fr.FTUKey, d.FTU_ID, fr.ReadingTimestamp,
CASE
WHEN fr.UA_Voltage < 30 AND fr.UB_Voltage > 180 AND fr.UC_Voltage > 180 THEN 'A相失压'
WHEN fr.UB_Voltage < 30 AND fr.UA_Voltage > 180 AND fr.UC_Voltage > 180 THEN 'B相失压'
WHEN fr.UC_Voltage < 30 AND fr.UA_Voltage > 180 AND fr.UB_Voltage > 180 THEN 'C相失压'
WHEN fr.UA_Voltage < 30 AND fr.UB_Voltage < 30 AND fr.UC_Voltage > 180 THEN 'A-B相失压'
WHEN fr.UB_Voltage < 30 AND fr.UC_Voltage < 30 AND fr.UA_Voltage > 180 THEN 'B-C相失压'
WHEN fr.UC_Voltage < 30 AND fr.UA_Voltage < 30 AND fr.UB_Voltage > 180 THEN 'C-A相失压'
END AS fault_type
FROM FactPowerReadings fr
JOIN DimFTU d ON fr.FTUKey = d.FTUKey
WHERE
((fr.UA_Voltage < 30 AND fr.UB_Voltage > 180 AND fr.UC_Voltage > 180) OR
(fr.UB_Voltage < 30 AND fr.UA_Voltage > 180 AND fr.UC_Voltage > 180) OR
(fr.UC_Voltage < 30 AND fr.UA_Voltage > 180 AND fr.UB_Voltage > 180) OR
(fr.UA_Voltage < 30 AND fr.UB_Voltage < 30 AND fr.UC_Voltage > 180) OR
(fr.UB_Voltage < 30 AND fr.UC_Voltage < 30 AND fr.UA_Voltage > 180) OR
(fr.UC_Voltage < 30 AND fr.UA_Voltage < 30 AND fr.UB_Voltage > 180))
AND fr.ReadingTimestamp > NOW() - INTERVAL '15 minutes';
电压骤降
WITH voltage_baseline AS (
SELECT
FTUKey,
AVG(UAB_Voltage) AS avg_uab,
AVG(UBC_Voltage) AS avg_ubc,
AVG(UCA_Voltage) AS avg_uca
FROM FactPowerReadings
WHERE ReadingTimestamp BETWEEN NOW() - INTERVAL '24 hours' AND NOW() - INTERVAL '1 hour'
GROUP BY FTUKey
)
SELECT
fr.FTUKey,
d.FTU_ID,
fr.ReadingTimestamp,
'Voltage Sag' AS fault_type,
ROUND((1 - LEAST(fr.UAB_Voltage/vb.avg_uab, fr.UBC_Voltage/vb.avg_ubc, fr.UCA_Voltage/vb.avg_uca)) * 100, 2) AS sag_percent
FROM FactPowerReadings fr
JOIN DimFTU d ON fr.FTUKey = d.FTUKey
JOIN voltage_baseline vb ON fr.FTUKey = vb.FTUKey
WHERE
(fr.UAB_Voltage < 0.9 * vb.avg_uab OR fr.UBC_Voltage < 0.9 * vb.avg_ubc OR fr.UCA_Voltage < 0.9 * vb.avg_uca) AND
(fr.UAB_Voltage > 0.1 * vb.avg_uab AND fr.UBC_Voltage > 0.1 * vb.avg_ubc AND fr.UCA_Voltage > 0.1 * vb.avg_uca) AND
fr.ReadingTimestamp > NOW() - INTERVAL '15 minutes';
欠电压
WITH sustained_undervoltage AS (
SELECT
FTUKey,
time_bucket('5 minute', ReadingTimestamp) AS bucket_time,
AVG(UAB_Voltage) AS avg_uab,
AVG(UBC_Voltage) AS avg_ubc,
AVG(UCA_Voltage) AS avg_uca,
COUNT(*) AS readings_count
FROM FactPowerReadings
WHERE ReadingTimestamp > NOW() - INTERVAL '1 hour'
GROUP BY FTUKey, time_bucket('5 minute', ReadingTimestamp)
HAVING COUNT(*) > 10 -- 确保有足够的数据点进行分析
)
SELECT
su.FTUKey,
d.FTU_ID,
su.bucket_time,
'Sustained Undervoltage' AS fault_type,
LEAST(su.avg_uab, su.avg_ubc, su.avg_uca) AS min_voltage
FROM sustained_undervoltage su
JOIN DimFTU d ON su.FTUKey = d.FTUKey
WHERE
su.avg_uab < 0.9 * 380 AND
su.avg_ubc < 0.9 * 380 AND
su.avg_uca < 0.9 * 380;
电压不平衡
WITH voltage_imbalance AS (
SELECT
FTUKey,
time_bucket('5 minute', ReadingTimestamp) AS bucket_time,
(MAX(GREATEST(UA_Voltage, UB_Voltage, UC_Voltage)) - MIN(LEAST(UA_Voltage, UB_Voltage, UC_Voltage))) /
NULLIF(AVG(GREATEST(UA_Voltage, UB_Voltage, UC_Voltage)), 0) * 100 AS imbalance_percent,
COUNT(*) AS readings_count
FROM FactPowerReadings
WHERE ReadingTimestamp > NOW() - INTERVAL '1 hour'
GROUP BY FTUKey, time_bucket('5 minute', ReadingTimestamp)
HAVING COUNT(*) > 10 -- 确保有足够的数据点进行分析
)
SELECT
vi.FTUKey,
d.FTU_ID,
vi.bucket_time,
'Voltage Imbalance' AS fault_type,
vi.imbalance_percent
FROM voltage_imbalance vi
JOIN DimFTU d ON vi.FTUKey = d.FTUKey
WHERE vi.imbalance_percent > 2; -- 电压不平衡超过2%
持续过载
WITH current_baseline AS (
SELECT
FTUKey,
PERCENTILE_CONT(0.95) WITHIN GROUP(ORDER BY IA_Current) AS p95_ia,
PERCENTILE_CONT(0.95) WITHIN GROUP(ORDER BY IB_Current) AS p95_ib,
PERCENTILE_CONT(0.95) WITHIN GROUP(ORDER BY IC_Current) AS p95_ic
FROM FactPowerReadings
WHERE ReadingTimestamp BETWEEN NOW() - INTERVAL '30 days' AND NOW() - INTERVAL '1 day'
GROUP BY FTUKey
),
sustained_overload AS (
SELECT
fr.FTUKey,
time_bucket('15 minute', fr.ReadingTimestamp) AS bucket_time,
AVG(fr.IA_Current) AS avg_ia,
AVG(fr.IB_Current) AS avg_ib,
AVG(fr.IC_Current) AS avg_ic,
cb.p95_ia AS threshold_ia,
cb.p95_ib AS threshold_ib,
cb.p95_ic AS threshold_ic
FROM FactPowerReadings fr
JOIN current_baseline cb ON fr.FTUKey = cb.FTUKey
WHERE fr.ReadingTimestamp > NOW() - INTERVAL '4 hours'
GROUP BY fr.FTUKey, time_bucket('15 minute', fr.ReadingTimestamp), cb.p95_ia, cb.p95_ib, cb.p95_ic
)
SELECT
so.FTUKey,
d.FTU_ID,
so.bucket_time,
'Sustained Overload' AS fault_type,
GREATEST(
so.avg_ia / NULLIF(so.threshold_ia, 0),
so.avg_ib / NULLIF(so.threshold_ib, 0),
so.avg_ic / NULLIF(so.threshold_ic, 0)
) * 100 AS overload_percent
FROM sustained_overload so
JOIN DimFTU d ON so.FTUKey = d.FTUKey
WHERE
(so.avg_ia > 1.2 * so.threshold_ia OR
so.avg_ib > 1.2 * so.threshold_ib OR
so.avg_ic > 1.2 * so.threshold_ic);
短时过载
WITH current_baseline AS (
SELECT
FTUKey,
PERCENTILE_CONT(0.99) WITHIN GROUP(ORDER BY IA_Current) AS p99_ia,
PERCENTILE_CONT(0.99) WITHIN GROUP(ORDER BY IB_Current) AS p99_ib,
PERCENTILE_CONT(0.99) WITHIN GROUP(ORDER BY IC_Current) AS p99_ic
FROM FactPowerReadings
WHERE ReadingTimestamp BETWEEN NOW() - INTERVAL '30 days' AND NOW() - INTERVAL '1 day'
GROUP BY FTUKey
)
SELECT
fr.FTUKey,
d.FTU_ID,
fr.ReadingTimestamp,
'Short-term Overload' AS fault_type,
GREATEST(
fr.IA_Current / NULLIF(cb.p99_ia, 0),
fr.IB_Current / NULLIF(cb.p99_ib, 0),
fr.IC_Current / NULLIF(cb.p99_ic, 0)
) * 100 AS overload_percent
FROM FactPowerReadings fr
JOIN DimFTU d ON fr.FTUKey = d.FTUKey
JOIN current_baseline cb ON fr.FTUKey = cb.FTUKey
WHERE
(fr.IA_Current > 1.5 * cb.p99_ia OR
fr.IB_Current > 1.5 * cb.p99_ib OR
fr.IC_Current > 1.5 * cb.p99_ic)
AND fr.ReadingTimestamp > NOW() - INTERVAL '15 minutes';
变压器过载
WITH power_baseline AS (
SELECT
FTUKey,
PERCENTILE_CONT(0.95) WITHIN GROUP(ORDER BY ApparentPower_Total) AS p95_power
FROM FactPowerReadings
WHERE ReadingTimestamp BETWEEN NOW() - INTERVAL '30 days' AND NOW() - INTERVAL '1 day'
GROUP BY FTUKey
),
sustained_power_overload AS (
SELECT
fr.FTUKey,
time_bucket('15 minute', fr.ReadingTimestamp) AS bucket_time,
AVG(fr.ApparentPower_Total) AS avg_power,
pb.p95_power AS threshold_power
FROM FactPowerReadings fr
JOIN power_baseline pb ON fr.FTUKey = pb.FTUKey
WHERE fr.ReadingTimestamp > NOW() - INTERVAL '2 hours'
GROUP BY fr.FTUKey, time_bucket('15 minute', fr.ReadingTimestamp), pb.p95_power
)
SELECT
spo.FTUKey,
d.FTU_ID,
spo.bucket_time,
'Transformer Overload' AS fault_type,
(spo.avg_power / NULLIF(spo.threshold_power, 0)) * 100 AS overload_percent
FROM sustained_power_overload spo
JOIN DimFTU d ON spo.FTUKey = d.FTUKey
JOIN DimXTU x ON d.XTUKey = x.XTUKey
WHERE
spo.avg_power > 1.1 * spo.threshold_power;
线路过载
WITH current_max AS (
SELECT
FTUKey,
time_bucket('10 minute', ReadingTimestamp) AS bucket_time,
MAX(GREATEST(IA_Current, IB_Current, IC_Current)) AS max_current
FROM FactPowerReadings
WHERE ReadingTimestamp > NOW() - INTERVAL '1 hour'
GROUP BY FTUKey, time_bucket('10 minute', ReadingTimestamp)
),
current_baseline AS (
SELECT
FTUKey,
PERCENTILE_CONT(0.95) WITHIN GROUP(ORDER BY GREATEST(IA_Current, IB_Current, IC_Current)) AS safe_current_limit
FROM FactPowerReadings
WHERE ReadingTimestamp BETWEEN NOW() - INTERVAL '30 days' AND NOW() - INTERVAL '1 day'
GROUP BY FTUKey
)
SELECT
cm.FTUKey,
d.FTU_ID,
cm.bucket_time,
'Line Overload' AS fault_type,
(cm.max_current / NULLIF(cb.safe_current_limit, 0)) * 100 AS overload_percent
FROM current_max cm
JOIN DimFTU d ON cm.FTUKey = d.FTUKey
JOIN current_baseline cb ON cm.FTUKey = cb.FTUKey
WHERE cm.max_current > 1.2 * cb.safe_current_limit;
开关设备过载
WITH switch_load AS (
SELECT
FTUKey,
time_bucket('15 minute', ReadingTimestamp) AS bucket_time,
MAX(GREATEST(IA_Current, IB_Current, IC_Current)) AS max_current,
VARIANCE(GREATEST(IA_Current, IB_Current, IC_Current)) AS current_variance
FROM FactPowerReadings
WHERE ReadingTimestamp > NOW() - INTERVAL '2 hours'
GROUP BY FTUKey, time_bucket('15 minute', ReadingTimestamp)
),
current_baseline AS (
SELECT
FTUKey,
PERCENTILE_CONT(0.99) WITHIN GROUP(ORDER BY GREATEST(IA_Current, IB_Current, IC_Current)) AS p99_current
FROM FactPowerReadings
WHERE ReadingTimestamp BETWEEN NOW() - INTERVAL '30 days' AND NOW() - INTERVAL '1 day'
GROUP BY FTUKey
)
SELECT
sl.FTUKey,
d.FTU_ID,
sl.bucket_time,
'Switch Equipment Overload' AS fault_type,
(sl.max_current / NULLIF(cb.p99_current, 0)) * 100 AS overload_percent
FROM switch_load sl
JOIN DimFTU d ON sl.FTUKey = d.FTUKey
JOIN current_baseline cb ON sl.FTUKey = cb.FTUKey
WHERE
sl.max_current > 1.3 * cb.p99_current AND
sl.current_variance > 50; -- 电流波动较大,可能是开关负载状态变化
导线断线
WITH phase_current_status AS (
SELECT
FTUKey,
ReadingTimestamp,
CASE WHEN IA_Current < 1 THEN TRUE ELSE FALSE END AS phase_a_zero,
CASE WHEN IB_Current < 1 THEN TRUE ELSE FALSE END AS phase_b_zero,
CASE WHEN IC_Current < 1 THEN TRUE ELSE FALSE END AS phase_c_zero,
CASE
WHEN IA_Current < 1 AND IB_Current > 5 AND IC_Current > 5 THEN 'A相断线'
WHEN IB_Current < 1 AND IA_Current > 5 AND IC_Current > 5 THEN 'B相断线'
WHEN IC_Current < 1 AND IA_Current > 5 AND IB_Current > 5 THEN 'C相断线'
END AS fault_phase
FROM FactPowerReadings
WHERE ReadingTimestamp > NOW() - INTERVAL '15 minutes'
)
SELECT
pcs.FTUKey,
d.FTU_ID,
pcs.ReadingTimestamp,
pcs.fault_phase AS fault_type
FROM phase_current_status pcs
JOIN DimFTU d ON pcs.FTUKey = d.FTUKey
WHERE
(pcs.phase_a_zero = TRUE AND pcs.phase_b_zero = FALSE AND pcs.phase_c_zero = FALSE) OR
(pcs.phase_a_zero = FALSE AND pcs.phase_b_zero = TRUE AND pcs.phase_c_zero = FALSE) OR
(pcs.phase_a_zero = FALSE AND pcs.phase_b_zero = FALSE AND pcs.phase_c_zero = TRUE);
接头断开
WITH current_stability AS (
SELECT
FTUKey,
time_bucket('5 minute', ReadingTimestamp) AS bucket_time,
AVG(IA_Current) AS avg_ia,
AVG(IB_Current) AS avg_ib,
AVG(IC_Current) AS avg_ic,
VARIANCE(IA_Current) AS var_ia,
VARIANCE(IB_Current) AS var_ib,
VARIANCE(IC_Current) AS var_ic,
MAX(IA_Current) / NULLIF(AVG(IA_Current), 0) AS max_avg_ratio_a,
MAX(IB_Current) / NULLIF(AVG(IB_Current), 0) AS max_avg_ratio_b,
MAX(IC_Current) / NULLIF(AVG(IC_Current), 0) AS max_avg_ratio_c
FROM FactPowerReadings
WHERE ReadingTimestamp > NOW() - INTERVAL '1 hour'
GROUP BY FTUKey, time_bucket('5 minute', ReadingTimestamp)
)
SELECT
cs.FTUKey,
d.FTU_ID,
cs.bucket_time,
CASE
WHEN cs.var_ia > 50 AND cs.max_avg_ratio_a > 2 THEN 'A相接头故障'
WHEN cs.var_ib > 50 AND cs.max_avg_ratio_b > 2 THEN 'B相接头故障'
WHEN cs.var_ic > 50 AND cs.max_avg_ratio_c > 2 THEN 'C相接头故障'
ELSE 'Unknown Connection Fault'
END AS fault_type
FROM current_stability cs
JOIN DimFTU d ON cs.FTUKey = d.FTUKey
WHERE
(cs.var_ia > 50 AND cs.max_avg_ratio_a > 2) OR
(cs.var_ib > 50 AND cs.max_avg_ratio_b > 2) OR
(cs.var_ic > 50 AND cs.max_avg_ratio_c > 2);
开关拒动
-- 注意:此查询需要结合开关操作信息,这里仅提供框架
-- 实际应用中需要增加开关操作记录表的关联
WITH switch_operations AS (
SELECT
FTUKey,
operation_time,
target_status
FROM switch_operation_log -- 假设的操作记录表
WHERE operation_time > NOW() - INTERVAL '24 hours'
),
current_changes AS (
SELECT
FTUKey,
ReadingTimestamp,
LAG(GREATEST(IA_Current, IB_Current, IC_Current)) OVER (
PARTITION BY FTUKey ORDER BY ReadingTimestamp
) AS previous_current,
GREATEST(IA_Current, IB_Current, IC_Current) AS current_current,
ABS(GREATEST(IA_Current, IB_Current, IC_Current) - LAG(GREATEST(IA_Current, IB_Current, IC_Current)) OVER (
PARTITION BY FTUKey ORDER BY ReadingTimestamp
)) / NULLIF(LAG(GREATEST(IA_Current, IB_Current, IC_Current)) OVER (
PARTITION BY FTUKey ORDER BY ReadingTimestamp
), 0) * 100 AS current_change_percent
FROM FactPowerReadings
WHERE ReadingTimestamp > NOW() - INTERVAL '24 hours'
)
SELECT
so.FTUKey,
d.FTU_ID,
so.operation_time,
'Switch Refusal to Operate' AS fault_type
FROM switch_operations so
JOIN DimFTU d ON so.FTUKey = d.FTUKey
LEFT JOIN current_changes cc ON
so.FTUKey = cc.FTUKey AND
cc.ReadingTimestamp BETWEEN so.operation_time AND so.operation_time + INTERVAL '5 minutes'
WHERE
(so.target_status = 'Open' AND cc.current_change_percent < 50) OR
(so.target_status = 'Close' AND cc.current_change_percent < 50);
熔断器熔断
WITH current_drop AS (
SELECT
FTUKey,
ReadingTimestamp,
LAG(IA_Current) OVER (PARTITION BY FTUKey ORDER BY ReadingTimestamp) AS prev_ia,
LAG(IB_Current) OVER (PARTITION BY FTUKey ORDER BY ReadingTimestamp) AS prev_ib,
LAG(IC_Current) OVER (PARTITION BY FTUKey ORDER BY ReadingTimestamp) AS prev_ic,
IA_Current,
IB_Current,
IC_Current,
CASE
WHEN LAG(IA_Current) OVER (PARTITION BY FTUKey ORDER BY ReadingTimestamp) > 5
AND IA_Current < 1 THEN 'A相熔断器熔断'
WHEN LAG(IB_Current) OVER (PARTITION BY FTUKey ORDER BY ReadingTimestamp) > 5
AND IB_Current < 1 THEN 'B相熔断器熔断'
WHEN LAG(IC_Current) OVER (PARTITION BY FTUKey ORDER BY ReadingTimestamp) > 5
AND IC_Current < 1 THEN 'C相熔断器熔断'
END AS fault_type
FROM FactPowerReadings
WHERE ReadingTimestamp > NOW() - INTERVAL '15 minutes'
)
SELECT
cd.FTUKey,
d.FTU_ID,
cd.ReadingTimestamp,
cd.fault_type
FROM current_drop cd
JOIN DimFTU d ON cd.FTUKey = d.FTUKey
WHERE
(cd.prev_ia > 5 AND cd.IA_Current < 1) OR
(cd.prev_ib > 5 AND cd.IB_Current < 1) OR
(cd.prev_ic > 5 AND cd.IC_Current < 1);
机械性断路
WITH circuit_break_pattern AS (
SELECT
FTUKey,
ReadingTimestamp,
CASE
WHEN IA_Current < 1 AND IB_Current < 1 AND IC_Current < 1
AND (UAB_Voltage > 300 OR UBC_Voltage > 300 OR UCA_Voltage > 300)
THEN 'Mechanical Circuit Break'
END AS fault_type
FROM FactPowerReadings
WHERE ReadingTimestamp > NOW() - INTERVAL '15 minutes'
)
SELECT
cbp.FTUKey,
d.FTU_ID,
cbp.ReadingTimestamp,
cbp.fault_type
FROM circuit_break_pattern cbp
JOIN DimFTU d ON cbp.FTUKey = d.FTUKey
WHERE cbp.fault_type IS NOT NULL;
为了整合所有故障类型的检测,可以创建一个综合故障检测存储过程或视图,例如:
CREATE OR REPLACE VIEW fault_detection_results AS
-- 短路故障检测
SELECT FTUKey, FTU_ID, detection_time, fault_type, 'Short Circuit' AS main_category
FROM three_phase_short_circuit_detection
UNION ALL
SELECT FTUKey, FTU_ID, detection_time, fault_type, 'Short Circuit' AS main_category
FROM two_phase_short_circuit_detection
UNION ALL
-- 接地故障检测
SELECT FTUKey, FTU_ID, detection_time, fault_type, 'Ground Fault' AS main_category
FROM single_phase_ground_fault_detection
UNION ALL
-- 失压故障检测
SELECT FTUKey, FTU_ID, detection_time, fault_type, 'Voltage Loss' AS main_category
FROM voltage_loss_detection
UNION ALL
-- 过载故障检测
SELECT FTUKey, FTU_ID, detection_time, fault_type, 'Overload' AS main_category
FROM overload_detection
UNION ALL
-- 断路故障检测
SELECT FTUKey, FTU_ID, detection_time, fault_type, 'Circuit Break' AS main_category
FROM circuit_break_detection;
这些SQL查询提供了基于遥测数据识别各类故障的基础框架。根据实际情况,可能需要调整阈值、时间窗口和判断逻辑,以提高故障检测的准确率和可靠性。