首页 > 试题广场 >

智能家居设备高能耗异常监控分析

[编程题]智能家居设备高能耗异常监控分析
  • 热度指数:218 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解

某智能家居服务商需要监控用户家中各类设备的电力消耗情况。系统需要定期分析每台设备的月度用电量,找出那些比同类设备(如所有“空调”或所有“热水器”)平均用电量更高的“高耗能设备”,并对这些设备生成简报,以便提醒用户检查设备是否老化或存在漏电风险。

表结构和字段说明:

  • 表1:smart_devices(智能设备信息表)

    • device_id(varchar): 设备唯一标识符,主键。
    • device_name(varchar): 设备名称(如 "Living Room AC")。
    • category(varchar): 设备类别(如 "HVAC", "Lighting", "Kitchen")。
    • location(varchar): 设备所在具体位置(如 "Living Room", "Master Bedroom")。
    • install_date(date): 设备安装日期。
  • 表2:energy_logs(能耗日志表)

    • log_id(int): 日志ID,主键。
    • device_id(varchar): 设备ID,逻辑关联smart_devices.device_id。
    • usage_kwh(decimal): 该时段消耗的电量(千瓦时),保留两位小数。
    • log_timestamp(datetime): 记录日志的具体时间点。
    • status(varchar): 设备状态("active", "standby", "error")。

问题

请编写SQL查询,找出在 2025年1月(2025-01-01 至 2025-01-31) 期间,总用电量 严格大于 其所属设备类别(category)下所有设备该月平均总用电量的设备。

查询结果要求:

  1. device_name:设备名称。
  2. location_code:位置代码。要求将location字段中的所有空格替换为下划线_,并将结果转换为全大写(例如 "Living Room" 变为 "LIVING_ROOM")。
  3. total_usage:该设备2025年1月的总用电量,结果保留2位小数(四舍五入)。
  4. efficiency_level:能效评级。根据该设备的总用电量判断:
    • 如果total_usage>= 50.00,显示 'High Load'
    • 如果total_usage< 50.00,显示 'Normal'
  5. 结果排序:优先按total_usage从高到低排序;如果用电量相同,则按device_id升序排序。
示例1

输入

-- 创建设备表
CREATE TABLE smart_devices (
    device_id VARCHAR(20) PRIMARY KEY,
    device_name VARCHAR(50),
    category VARCHAR(30),
    location VARCHAR(50),
    install_date DATE
);

-- 创建能耗日志表
CREATE TABLE energy_logs (
    log_id INT PRIMARY KEY,
    device_id VARCHAR(20),
    usage_kwh DECIMAL(10, 2),
    log_timestamp DATETIME,
    status VARCHAR(20)
);

-- 插入设备数据
INSERT INTO smart_devices VALUES ('D001', 'Master Bedroom AC', 'HVAC', 'Master Bedroom', '2024-05-20');
INSERT INTO smart_devices VALUES ('D002', 'Living Room AC', 'HVAC', 'Living Room', '2024-06-15');
INSERT INTO smart_devices VALUES ('D003', 'Kitchen Fridge', 'Kitchen', 'Kitchen Area', '2024-01-10');
INSERT INTO smart_devices VALUES ('D004', 'Smart Oven', 'Kitchen', 'Kitchen Area', '2024-11-05');
INSERT INTO smart_devices VALUES ('D005', 'Guest Room AC', 'HVAC', 'Guest Room', '2024-12-01');

-- 插入能耗日志数据 (2025年1月数据为主,包含少量干扰数据)
-- HVAC类: D001(Total: 40+25=65), D002(Total: 80+10=90), D005(Total: 20). Avg = (65+90+20)/3 = 58.33
-- Kitchen类: D003(Total: 30), D004(Total: 10). Avg = 20.
INSERT INTO energy_logs VALUES (1, 'D001', 40.00, '2025-01-05 10:00:00', 'active');
INSERT INTO energy_logs VALUES (2, 'D001', 25.00, '2025-01-20 14:00:00', 'active');
INSERT INTO energy_logs VALUES (3, 'D002', 80.00, '2025-01-15 18:00:00', 'active');
INSERT INTO energy_logs VALUES (4, 'D002', 10.00, '2025-01-16 09:00:00', 'standby');
INSERT INTO energy_logs VALUES (5, 'D003', 30.00, '2025-01-10 12:00:00', 'active'); -- 高于Kitchen平均
INSERT INTO energy_logs VALUES (6, 'D004', 10.00, '2025-01-12 18:00:00', 'active');
INSERT INTO energy_logs VALUES (7, 'D005', 20.00, '2025-01-25 20:00:00', 'active');
INSERT INTO energy_logs VALUES (8, 'D002', 50.00, '2024-12-31 23:59:00', 'active'); -- 干扰数据:非2025年1月

输出

device_name|location_code|total_usage|efficiency_level
Living Room AC|LIVING_ROOM|90.00|High Load
Master Bedroom AC|MASTER_BEDROOM|65.00|High Load
Kitchen Fridge|KITCHEN_AREA|30.00|Normal

说明

解析逻辑:

  • HVAC类:D001(65), D002(90), D005(20)。平均值 = (65+90+20)/3 = 58.33。
    • D001 (65 > 58.33) -> 选中。Location: MASTER_BEDROOM.
    • D002 (90 > 58.33) -> 选中。Location: LIVING_ROOM.
    • D005 (20 < 58.33) -> 排除。
  • Kitchen类:D003(30), D004(10)。平均值 = (30+10)/2 = 20.00。
    • D003 (30 > 20) -> 选中。Location: KITCHEN_AREA.
  • 排序:Total Usage 降序 (90 -> 65 -> 30)。
device_namelocation_codetotal_usageefficiency_level
Living Room ACLIVING_ROOM90.00High Load
Master Bedroom ACMASTER_BEDROOM65.00High Load
Kitchen FridgeKITCHEN_AREA30.00Normal
WITH monthly_usage AS (
    -- 计算每个设备在2025年1月的总用电量
    SELECT 
        d.device_id,
        d.device_name,
        d.category,
        d.location,
        COALESCE(SUM(e.usage_kwh), 0) AS total_usage_raw
    FROM smart_devices d
    LEFT JOIN energy_logs e ON d.device_id = e.device_id
        AND e.log_timestamp >= '2025-01-01 00:00:00'
        AND e.log_timestamp <= '2025-01-31 23:59:59'
        AND e.status = 'active'  -- 只考虑active状态的记录
    GROUP BY d.device_id, d.device_name, d.category, d.location
),
category_stats AS (
    -- 计算每个设备类别的平均用电量
    SELECT 
        device_id,
        device_name,
        category,
        location,
        total_usage_raw,
        -- 窗口函数:计算每个类别下所有设备的平均用电量
        AVG(total_usage_raw) OVER(PARTITION BY category) AS category_avg_usage
    FROM monthly_usage
),
filtered_devices AS (
    -- 筛选出用电量大于类别平均值的设备
    SELECT 
        device_id,
        device_name,
        category,
        location,
        ROUND(total_usage_raw, 2) AS total_usage,
        category_avg_usage
    FROM category_stats
    WHERE total_usage_raw > category_avg_usage
        AND total_usage_raw > 0  -- 确保设备有实际用电量
)
SELECT 
    fd.device_name,
    UPPER(REPLACE(fd.location, ' ', '_')) AS location_code,
    fd.total_usage,
    CASE 
        WHEN fd.total_usage >= 50.00 THEN 'High Load'
        ELSE 'Normal'
    END AS efficiency_level
FROM filtered_devices fd
ORDER BY 
    fd.total_usage DESC,
    fd.device_id ASC;
发表于 2026-02-03 23:09:08 回复(0)
-- 1对多对多  一个类别多个设备,一个设备多个记录

-- 每个设备的总用电量
with total_tb as (
    select
        device_id
        ,round(sum(usage_kwh), 2) as total_usage  -- 每个设备的总电量
    from
        energy_logs 
    where
        log_timestamp >= '2025-01-01' and log_timestamp < '2025-02-01'
    group by 
        device_id
),

-- 每个类别的平均用电量
avg_tb as (
    select
        d.category
        ,avg(t.total_usage) as avg_usage       
    from
        smart_devices as d
        inner join total_tb as t on d.device_id=t.device_id
    group by 
        d.category
)

-- 输出
select
    d.device_name
    ,upper(replace(d.location,' ', '_'))  as location_code
    ,t.total_usage    
    ,case when total_usage >= 50.00 then 'High Load' else 'Normal' end  as efficiency_level      
from 
    smart_devices as d
    inner join total_tb  as t on d.device_id=t.device_id
    inner join avg_tb as a on d.category =a.category
where
    t.total_usage > a.avg_usage
order by 
    t.total_usage desc ,d.device_id asc ;

发表于 2026-02-03 20:07:59 回复(0)
select
    device_name,
    location_code,
    total_usage,
    efficiency_level
from
    (
        select
            s.device_name,
            upper(
                replace
                    (s.location, ' ', '_')
            ) as location_code,
            round(sum(usage_kwh), 2) as total_usage,
            case
                when round(sum(usage_kwh), 2) >= 50.00 then 'High Load'
                else 'Normal'
            end as efficiency_level,
            case
                when round(sum(usage_kwh), 2) > avg(round(sum(usage_kwh), 2)) over (
                    partition by
                        s.category
                ) then 1
                else 0
            end as avg_or_not
        from
            smart_devices as s
            join energy_logs as e on s.device_id = e.device_id
        where
            date_format(e.log_timestamp, '%Y-%m') = '2025-01'
        group by
            s.device_id,
            s.device_name,
            s.location,
            s.category
        order by
            total_usage desc,
            s.device_id
    ) as tmp
where
    avg_or_not = 1

avg() over()的使用

发表于 2026-02-01 18:21:43 回复(0)
select device_name,upper(replace(location,' ','_')) location_code,total_usage,
    case when total_usage >=50 then 'High Load' else 'Normal' end efficiency_level
from ( 
    # 1、类别平均用电
    select device_name,device_id,category,location,total_usage,
        avg(total_usage)over(partition by category) category_avg_usage
    
    from (
        # 2、设备总用电
        select 
            distinct device_name,device_id,category,location,
            sum(usage_kwh)over(partition by device_name) total_usage
        from energy_logs join smart_devices using(device_id)
        where log_timestamp like '2025-01%'
    )a
)b
# 3、总用电量 > 类别平均用电
where total_usage>category_avg_usage
order by total_usage desc ,device_id

发表于 2026-02-01 12:49:30 回复(0)
with cnt_device as (
    select category,count(device_id) as cnt_device
    from
        (select distinct el.device_id,category
        from smart_devices sd
        inner join energy_logs el on sd.device_id = el.device_id
        where date(log_timestamp) between '2025-01-01' and '2025-01-31') device_new
    group by category
)

select device_name,
       upper(replace(location,' ','_')) as location_code,
       sum_usage_kwh as total_usage,
       case when sum_usage_kwh>=50 then 'High Load' else 'Normal' end as efficiency_level
from
    (select distinct
        sd.device_id,sd.category,device_name,
        location,
        sum(usage_kwh) over(partition by el.device_id) as sum_usage_kwh,
        sum(usage_kwh) over(partition by category) as sum_all_usage_kwh
    from smart_devices sd
    inner join energy_logs el on sd.device_id = el.device_id
    where date(log_timestamp) between '2025-01-01' and '2025-01-31') new
inner join cnt_device cd on cd.category = new.category
where sum_usage_kwh>sum_all_usage_kwh/cnt_device
order by total_usage desc ,device_id

发表于 2026-02-01 11:04:28 回复(0)