mysql - 基于 SQL Server 的有限时间段内的小组系列

标签 mysql sql sql-server

我有一个包含用户和日期值的表。对于每个用户可以有多个日期值。在下面的脚本中,我根据我在 stackoverflow 上找到的另一个答案,在选择期间为每个用户插入了sincePrevious 和sinceFirst 列。

SELECT 
 a.user as 'user'
,a.date as 'date'
,ISNULL(DATEDIFF(day,b.date,a.date),0) as 'sincePrevious'
,datediff(day, min(a.date) over (partition by a.user), a.date) as 'sinceFirst'
FROM
(select  *,ROW_NUMBER() OVER(PARTITION BY user ORDER BY date) as Rank from HUT_regels) as a
LEFT JOIN 
(select  *,ROW_NUMBER() OVER(PARTITION BY user ORDER BY date) as Rank from HUT_regels) as b
ON a.user = b.user AND a.Rank = b.Rank + 1
ORDER by 'user', 'date'

我想要做的是以类似的方式插入另一列(在选择期间),该列根据用户值和两行之间的时间差添加唯一的组 ID。在示例中,我添加了一些 groupId。当同一用户的两个连续日期之间的日期差异大于 50 天(在此示例中)时,这必须被视为新的事件“序列”。 groupID 2、3 和 4 反射(reflect)了这一点。

user      date        sincePrevious  sinceFirst  groupId
100000029 25-05-2012  0              0           1
100002161 08-01-2012  0              0           2
100002161 04-02-2012  27             27          2
100002161 15-02-2012  11             38          2
100002161 28-03-2012  42             80          2
100002161 23-05-2012  56             136         3
100002161 11-07-2012  49             185         3
100002161 29-08-2012  49             234         3
100002161 24-10-2012  56             290         4
100002161 21-11-2012  28             318         4
100005242 07-05-2013  0              0           5
100005242 10-05-2013  3              3           5
100005242 14-05-2013  4              7           5
100005242 17-05-2013  3              10          5
100005242 21-05-2013  4              14          5
100005242 24-05-2013  3              17          5
100005242 28-05-2013  4              21          5
100005242 07-06-2013  10             31          5
...

groupId 应该是唯一的,但不必是连续的或偶数。

我知道这可以通过 CTE 实现,但希望找到一种类似于生成sincePrevious 和sinceFirst 的解决方案。

我的用例是 SQL Server,但更通用的解决方案(我提到了 MySQL,但例如 PostgreSQL 也很好)也可以帮助其他人。

最佳答案

首先,您应该使用 lag()min() 来获取值:

select r.*,
       datediff(day, lag(date) over (partition by user order by date), date) as sincePrevious,
       datediff(day, min(date) over (partition by user), date) as sinceFirst
from HUT_regels r;

要添加GroupId,您只需要一个子查询和条件聚合:

select r.*,
       sum(case when sincePrevious < 0 then 0 else 1 end) over
           (partition by user order by date) as groupId
from (select r.*,
             datediff(day, lag(date) over (partition by user order by date), date) as sincePrevious,
             datediff(day, min(date) over (partition by user), date) as sinceFirst
      from HUT_regels r
     ) r;

这都是 ANSI 标准功能。但是,直到 2012 版本,它才在 SQL Server 中完全引入。在早期版本中,您可以使用 apply 代替。

关于mysql - 基于 SQL Server 的有限时间段内的小组系列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37725365/

相关文章:

java - 访问 GAE DB 给出 AccessControlException

mysql - 查询逻辑解决方案

php - 提供的参数不是有效的mySQL资源

c# - 如何获取从网站上传的 Excel 文件并以编程方式将数据导入 SQL Server?

sql-server - T-SQL:获取全部,但在 'not null' 上加入

sql - 如果满足某些条件,如何将多个列设置为空?

php - 在哪里以及如何存储汇率?

sql - 限制表只有一行

mysql - SQL 导入 PostgreSQL 8.4.20 失败并出现语法错误

mysql - 如何获取组的 mysql 总行数百分比?