You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于SQL数据库的废弃物管理系统风险因子计算优化求助

优化废弃物管理系统的风险因子计算SQL视图

我正在开发一套废弃物管理系统,需要依据工业污水、生活污水等不同废弃物的风险因子优先安排处置动作。系统采用SQL数据库存储污染对象的年龄、位置、污染类型等信息,但在创建RiskReport视图计算风险因子时,结果不符合预期,尤其是无法正确纳入水体邻近标准。我需要优化SQL代码,让视图输出包含nearWaterRisk、nearCityRisk、distanceToWater、distanceToCity字段的结果,且水体风险优先级高于城区风险。

数据库架构

-- Contaminated objects table
CREATE TABLE ContaminatedObject (
    id INTEGER PRIMARY KEY,
    name TEXT,
    age INTEGER,
    position POINT,
    extension REAL
);

-- Sewage contamination table
CREATE TABLE SewageContamination (
    id INTEGER PRIMARY KEY,
    contaminatedObjectId INTEGER,
    sewageType TEXT,
    sewageVolume FLOAT,
    owner TEXT,
    FOREIGN KEY (contaminatedObjectId) REFERENCES ContaminatedObject(id)
);

-- Industrial contamination table
CREATE TABLE IndustrialContamination (
    id INTEGER PRIMARY KEY,
    contaminatedObjectId INTEGER,
    industrialWasteType TEXT,
    industrialWasteVolume TEXT,
    owner TEXT,
    FOREIGN KEY (contaminatedObjectId) REFERENCES ContaminatedObject(id)
);

-- Issues table
CREATE TABLE Issue (
    id INTEGER PRIMARY KEY,
    objectId INTEGER,
    issueType TEXT,
    date TIMESTAMP,
    documentation TEXT,
    FOREIGN KEY (objectId) REFERENCES ContaminatedObject(id)
);

-- Historical records table for documentation
CREATE TABLE HistoricalRecord (
    id INTEGER PRIMARY KEY,
    objectId INTEGER,
    action TEXT,
    timestamp TIMESTAMP,
    FOREIGN KEY (objectId) REFERENCES ContaminatedObject(id)
);

-- City bodies table
CREATE TABLE City (
    id INTEGER PRIMARY KEY,
    cityName TEXT,
    position POINT
);

-- Water bodies table
CREATE TABLE WaterBody (
    id INTEGER PRIMARY KEY,
    waterBodyname TEXT,
    position POINT
);

样本数据

-- Insert sample data into the ContaminatedObject table
INSERT INTO ContaminatedObject (name, age, position, extension) VALUES
    ('Object 1', 20, ST_GeomFromText('POINT(10 20)'), 50.5),
    ('Object 2', 30, ST_GeomFromText('POINT(30 40)'), 60.7),
    ('Object 3', 25, ST_GeomFromText('POINT(50 60)'), 70.2);

-- Insert sample data into the SewageContamination table
INSERT INTO SewageContamination (contaminatedObjectId, sewageType, sewageVolume, owner) VALUES
    (1, 'chromium', 100.5, 'Owner A'),
    (2, 'arsenic', 200.7, 'Owner B');

-- Insert sample data into the IndustrialContamination table
INSERT INTO IndustrialContamination (contaminatedObjectId, industrialWasteType, industrialWasteVolume, owner) VALUES
    (1, 'arsenic', 145, 'Owner C'),
    (3, 'arsenic', 105, 'Owner D');

-- Insert sample data into the City table
INSERT INTO City (cityName, position) VALUES
    ('City 1', ST_GeomFromText('POINT(15 25)'));

-- Insert sample data into the WaterBody table
INSERT INTO WaterBody (waterBodyname, position) VALUES
    ('Lake 1', ST_GeomFromText('POINT(20 30)')),
    ('Lake 2', ST_GeomFromText('POINT(40 50)'));

动作优先级判定标准

  • 年限标准:使用年限超过40年的设施优先检查
  • 水体邻近标准:距离水体250米以内的设施因污染水体风险高需优先处理
  • 分类标准:需考虑污染类型、污染量、与城区的距离等因素

优化后的RiskReport视图实现

核心思路

  1. 计算每个污染对象到最近水体/城区的实际地理距离
  2. 基于距离阈值生成nearWaterRisk和nearCityRisk标识
  3. 整合年限、污染类型、污染量等因子计算综合风险得分,赋予水体风险更高权重
  4. 按水体风险优先、综合得分降序排序,满足处置优先级要求

视图SQL代码(兼容PostGIS/MySQL)

CREATE OR REPLACE VIEW RiskReport AS
WITH ObjectDistances AS (
    SELECT
        co.id AS objectId,
        co.name,
        co.age,
        co.position,
        -- 计算到最近水体的距离(PostGIS用ST_Distance,MySQL替换为ST_Distance_Sphere)
        MIN(ST_Distance(co.position, wb.position)) AS distanceToWater,
        -- 计算到最近城区的距离
        MIN(ST_Distance(co.position, c.position)) AS distanceToCity
    FROM ContaminatedObject co
    CROSS JOIN WaterBody wb
    CROSS JOIN City c
    GROUP BY co.id, co.name, co.age, co.position
),
ContaminationDetails AS (
    SELECT
        co.id AS objectId,
        -- 合并并去重污水污染类型
        GROUP_CONCAT(DISTINCT sc.sewageType) AS sewageTypes,
        -- 累计污水总量,空值补0
        COALESCE(SUM(sc.sewageVolume), 0) AS totalSewageVolume,
        -- 合并并去重工业污染类型
        GROUP_CONCAT(DISTINCT ic.industrialWasteType) AS industrialWasteTypes,
        -- 累计工业废弃物总量,空值补0并转换为数值类型
        COALESCE(SUM(CAST(ic.industrialWasteVolume AS FLOAT)), 0) AS totalIndustrialWasteVolume
    FROM ContaminatedObject co
    LEFT JOIN SewageContamination sc ON co.id = sc.contaminatedObjectId
    LEFT JOIN IndustrialContamination ic ON co.id = ic.contaminatedObjectId
    GROUP BY co.id
)
SELECT
    od.objectId,
    od.name,
    od.age,
    -- 保留原始距离值,保留2位小数
    ROUND(od.distanceToWater, 2) AS distanceToWater,
    ROUND(od.distanceToCity, 2) AS distanceToCity,
    -- 水体邻近风险:250米以内标记为高风险(1=高风险,0=低风险)
    CASE WHEN od.distanceToWater <= 250 THEN 1 ELSE 0 END AS nearWaterRisk,
    -- 城区邻近风险:示例阈值设为500米,可根据业务调整
    CASE WHEN od.distanceToCity <= 500 THEN 1 ELSE 0 END AS nearCityRisk,
    -- 综合风险得分:权重向水体风险倾斜
    (
        -- 年限风险:超过40年加20分
        CASE WHEN od.age > 40 THEN 20 ELSE 0 END
        -- 水体风险:高风险加60分(最高权重)
        + (od.nearWaterRisk * 60)
        -- 城区风险:高风险加20分
        + (od.nearCityRisk * 20)
        -- 污染量风险:每100单位加10分
        + (ROUND((cd.totalSewageVolume + cd.totalIndustrialWasteVolume) / 100) * 10)
        -- 高危污染物(砷、铬)加15分,可扩展更多类型
        + CASE 
            WHEN cd.sewageTypes LIKE '%arsenic%' 
                OR cd.sewageTypes LIKE '%chromium%' 
                OR cd.industrialWasteTypes LIKE '%arsenic%' 
                OR cd.industrialWasteTypes LIKE '%chromium%' 
            THEN 15 ELSE 0 
        END
    ) AS totalRiskScore
FROM ObjectDistances od
JOIN ContaminationDetails cd ON od.objectId = cd.objectId
-- 排序规则:水体风险优先,再按综合得分降序
ORDER BY nearWaterRisk DESC, totalRiskScore DESC;

关键细节说明

  • 距离计算适配:MySQL环境需将ST_Distance替换为ST_Distance_Sphere,该函数返回以米为单位的球面距离,符合实际地理空间计算需求
  • 空值处理:用COALESCE确保无污染记录的对象不会出现NULL值,避免计算错误
  • 权重调整:可根据业务需求修改得分公式中的权重(比如调整水体风险的分值占比)
  • 高危污染物扩展:可在CASE语句中添加更多高危污染物类型,适配不同场景

查询结果示例

执行SELECT * FROM RiskReport;将得到包含所有目标字段的结果,且水体高风险对象会排在最前面,完全符合优先级要求。


内容的提问来源于stack exchange,提问作者Apoas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 13:44:56