某水表量每15分钟一报,然后某天示数清0了,重新报示值了 ,如何写sql 计算每日水量

要计算每日电量,需处理电表清零的情况。以下是针对不同数据库的解决方案:

方法思路

  1. 识别清零点:通过比较当前值与前一个值,若当前值明显变小(如小于前值的10%),则视为清零。
  2. 分段累计:将数据按清零点分段,每段单独累计电量。
  3. 每日汇总:按日期分组,累加每日各段的电量总和。

SQL 实现(以 MySQL 为例)

sql 复制代码
WITH RECURSIVE
-- 1. 添加行号和前一个值
t1 AS (
    SELECT
        `timestamp`,
        value,
        ROW_NUMBER() OVER (ORDER BY `timestamp`) AS rn,
        LAG(value) OVER (ORDER BY `timestamp`) AS prev_value
    FROM meter_data
),
-- 2. 标记清零点(当前值 < 前值的10%)
t2 AS (
    SELECT
        `timestamp`,
        value,
        rn,
        prev_value,
        CASE WHEN prev_value IS NOT NULL AND value < prev_value * 0.1 THEN 1 ELSE 0 END AS is_reset
    FROM t1
),
-- 3. 为每个清零点分配组ID(使用递归CTE)
t3 AS (
    SELECT
        `timestamp`,
        value,
        rn,
        is_reset,
        rn AS group_id
    FROM t2
    WHERE rn = 1
    
    UNION ALL
    
    SELECT
        t2.`timestamp`,
        t2.value,
        t2.rn,
        t2.is_reset,
        CASE WHEN t2.is_reset = 1 THEN t2.rn ELSE t3.group_id END
    FROM t2
    JOIN t3 ON t2.rn = t3.rn + 1
),
-- 4. 计算每组的增量并累加
t4 AS (
    SELECT
        `timestamp`,
        DATE(`timestamp`) AS date,
        value,
        group_id,
        value - LAG(value, 1, value) OVER (PARTITION BY group_id ORDER BY `timestamp`) AS increment
    FROM t3
)
-- 5. 按日期汇总电量(忽略负值,可能是异常或清零残留)
SELECT
    date,
    SUM(CASE WHEN increment >= 0 THEN increment ELSE 0 END) AS daily_energy
FROM t4
GROUP BY date
ORDER BY date;

其他数据库适配

  • PostgreSQL :与 MySQL 类似,但递归 CTE 语法更简洁:

    sql 复制代码
    WITH RECURSIVE t3 AS (...)
  • SQL Server :使用 ISNULL 替代 COALESCE,窗口函数语法相同。

  • Oracle :使用 CONNECT BY 替代递归 CTE,或用 MATCH_RECOGNIZE 简化模式匹配。

关键点说明

  1. 清零判断 :value < prev_value * 0.1 可根据实际情况调整阈值。
  2. 分组逻辑 :通过递归 CTE 为每个清零点分配新的 group_id。
  3. 处理异常值 :SUM(CASE WHEN increment >= 0 ...) 过滤可能的负值(如清零残留)。

示例数据验证

假设有以下数据(每15分钟记录一次):

timestamp value
2023-01-01 00:00:00 100
2023-01-01 00:15:00 110
2023-01-01 23:45:00 900
2023-01-02 00:00:00 50
2023-01-02 23:45:00 800

计算结果:

date daily_energy
2023-01-01 800
2023-01-02 750

优化建议

  1. 预处理数据:若频繁查询,可将分组结果存储为物化视图。
  2. 索引优化 :确保 timestamp 字段有索引,加速排序和窗口函数计算。
  3. 动态阈值:根据历史数据动态调整清零判断阈值,提高准确性。
复制代码

方法二

sql 复制代码
 with a1 as(
	select  * 
	from (
   --查询有清0 的表
	   SELECT
		  Id, ProjectId, fd,val,dot,PointId,
			LAG(val) OVER (PARTITION BY  ProjectId,PointId ORDER BY dot asc,val desc) AS prev_value , 
			LAG(Id) OVER (PARTITION BY  ProjectId,PointId ORDER BY dot asc,val desc) AS prev_Id 
		
		FROM table1
		where fd >='2025-05-06'
	  and fd<='2025-05-07'
	   and dot<='2025-05-07 00:00:00'
	   and ProjectId=170132 
	) as  t
	where 1=1
	and val < prev_value * 0.1
 ),
 av3 as(
      --查询有清0 的表的最后一条数据
       select  *  from (
      select a.id,a.PointId,a.fd,  ROW_NUMBER() OVER (PARTITION BY  a.ProjectId,a.PointId ORDER BY a.dot desc,a.val desc) AS rn
	  from a1 t1,table1 a
	  where t1.PointId=a.pointId  and t1.dot<a.dot
	and  a.fd >='2025-05-06'
 and a.fd<='2025-05-07'
 and a.dot<='2025-05-07 00:00:00'
	) as t
	where t.rn=1
	  
 ) ,
 a2 as (
       --查询有清0 的表的前一条数据,当前数据 和最后一条数据的
       select   a.*,-1 as preItem  from a1,table1 a
	   where a1.prev_Id=a.Id 
	   union all
	   select   a.*,0 as preItem  from a1,table1 a
	   where a1.id=a.Id  
	   union all
	   select   a.*,1 as preItem  from av3 a3,table1 a
	   where a3.id=a.Id  
 )
 
 select  *  from  av3
相关推荐
讯捷蓝达1 分钟前
机房突发断电,5 盘 RAID硬盘全部掉线: 急速上门救援,现场4小时华为2288H V5服务器数据完整恢复
运维·服务器·数据库
Pniubi6 分钟前
介绍一下我的agent项目中记忆、RAG系统的相关数据库
数据库
ly768912 分钟前
性能剖析与压测方法论:JMH、async-profiler 与分层瓶颈定位的可复现实验
服务器·前端·数据库·压测·jmh·性能剖析·async-profiler
longerxin202013 分钟前
Ubuntu 22.04 ARM64 云镜像开启 root 密钥登录(保留 ubuntu 密钥登录,禁止密码登录)
数据库·ubuntu·postgresql
OxYGC29 分钟前
[工程] Redis 配置文件redis.conf全解析
数据库·redis·bootstrap
YuanDaima204838 分钟前
系统架构与数据库理论基础:PostgreSQL 与 pgvector
数据库·人工智能·docker·postgresql·系统架构·产品经理
跨境数据猎手2 小时前
跨境电商系统三大 Web 漏洞的防护:SQL 注入、XSS、CSRF
前端·sql·xss
2601_957084844 小时前
2026年生产型服装供应链SCM系统丨水洗参数、产能与验收节点架构
数据库·scm·服装供应链系统·服装scm·服装供应链
IvorySQL9 小时前
PostgreSQL 日报|恢复期 COPY TO 未日志表修复(10 月 21 日)
数据库·postgresql·区块链
贝猫说python10 小时前
大模型比赛2.3智能体开发(工具调用智能问答助手)
数据库·oracle