当前位置: 首页 > 技术教程

怎么让数据库统计连续相同数据?

  要让数据库统计连续相同的数据,例如连续登录天数、连续相同状态记录等,可以通过窗口函数或自连接实现,计算行号差值标记连续分组,再统计每组长度。以下是几种常见数据库的实现方法,以及具体示例。

  怎么让数据库统计连续相同数据?

  方法一:使用窗口函数

  窗口函数如 ROW_NUMBER()、LAG()/LEAD()可以高效地标记连续数据的分组,然后通过 GROUP BY 统计。

  示例场景

  假设有一个表 user_logins,记录用户每日登录状态:

  sqlCREATE TABLE user_logins (user_id INT,login_date DATE,is_login INT -- 1=登录, 0=未登录);

  目标:统计每个用户连续登录的最大天数。

  实现步骤

  标记连续登录的分组

  使用 LAG() 获取前一天的登录状态,若与当前不同,则分组号 grp 递增。

  按用户和分组统计连续天数

  使用 GROUP BY 计算每个分组的记录数。

  找出最大连续天数

  使用 MAX() 获取每个用户的最大连续登录天数。

  SQL 代码(MySQL 8.0+/PostgreSQL/SQL Server)

  sqlWITH marked_logins AS (SELECT user_id,login_date,is_login,-- 若前一天未登录或不存在,则新分组SUM(CASE WHEN is_login = 1 AND LAG(is_login) OVER (PARTITION BY user_id ORDER BY login_date) != 1 OR LAG(is_login) OVER (PARTITION BY user_id ORDER BY login_date) IS NULL THEN 1 ELSE 0 END) OVER (PARTITION BY user_id ORDER BY login_date) AS grpFROM user_logins),consecutive_days AS (SELECT user_id,grp,COUNT(*) AS consecutive_countFROM marked_loginsWHERE is_login = 1 -- 只统计登录的记录GROUP BY user_id, grp)SELECT user_id,MAX(consecutive_count) AS max_consecutive_daysFROM consecutive_daysGROUP BY user_id;

  简化版

  如果数据是连续的数值,且需统计连续相同值的区间长度,可以这样优化:

  sqlWITH numbered_data AS (SELECT id,value,ROW_NUMBER() OVER (ORDER BY id) AS row_numFROM your_table),grouped_data AS (SELECT id,value,row_num - ROW_NUMBER() OVER (PARTITION BY value ORDER BY row_num) AS grpFROM numbered_data)SELECT value,COUNT(*) AS consecutive_countFROM grouped_dataGROUP BY value, grp;

怎么让数据库统计连续相同数据.jpg

  方法二:使用自连接

  如果数据库不支持窗口函数,可以通过自连接实现。

  示例场景

  统计表 weather 中连续相同温度的天数:

  sqlCREATE TABLE weather (id INT,record_date DATE,temperature INT);

  实现步骤

  自连接匹配连续日期

  通过 DATEDIFF(a.record_date, b.record_date) = 1 匹配相邻日期的记录。

  分组统计连续相同温度

  使用 GROUP BY 计算连续相同温度的区间长度。

  SQL 代码

  sqlSELECT a.temperature,COUNT(*) AS consecutive_daysFROM weather aJOIN weather b ON DATEDIFF(a.record_date, b.record_date) = 1 AND a.temperature = b.temperatureGROUP BY a.temperature;

  注意:此方法可能漏统计部分边界情况,需结合递归查询或存储过程优化。

  方法三:使用递归查询

  对于需要递归处理连续区间的问题,可以使用递归 CTE。

  示例场景

  统计股票连续上涨的天数:

  sqlWITH RECURSIVE consecutive_increases AS (-- 基础查询:找到第一天或上涨的起点SELECT id,price,1 AS consecutive_countFROM stocksWHERE id = 1 -- 或其他起始条件union ALL-- 递归部分:匹配连续上涨的记录SELECT s.id,s.price,CASE WHEN s.price > prev.price THEN prev.consecutive_count + 1 ELSE 1 ENDFROM stocks sJOIN consecutive_increases prev ON s.id = prev.id + 1)SELECT MAX(consecutive_count) AS max_consecutive_increasesFROM consecutive_increases;

  以上就是数据库统计连续相同数据的详细步骤,不同的方法适用于不支持窗口函数的数据库。通过自连接匹配相邻记录,递归计算连续区间,跟着小编一起详细了解下吧。


猜你喜欢