我有很多日期/时间的项目。
[自动增量],[last_modified_date]
item1,2013-sep-01 11:01:01
item2,2013-sep-01 11:01:02
item3,2013-sep-01 11:10:04
item4,2013-sep-01 11:10:05
item5,2013-sep-01 11:10:06
item6,2013-sep-02 10:10:01
item7,2013-sep-02 10:10:01
我需要按日期对项目进行分组,但分组必须支持几秒钟的错误阈值(比方说4秒)。我想把这作为新的结果。
[自动增量],[last_modified_date]
group1,2013-sep-01 11:01:01
group2,2013-sep-01 11:10:04
group3,2013-sep-02 10:10:01item1,2013-sep-01 11:01:01,group1
item2,2013-sep-01 11:01:02,group1
item3,2013-sep-01 11:10:04,group2
item4,2013-sep-01 11:10:05,group2
item5,2013-sep-01 11:10:06,group2
item6,2013-sep-02 10:10:01,group3
item7,2013-sep-02 10:10:01,group3
我可以通过循环所有项目来轻松完成,检查组是否存在,如果不存在则添加新组。
从abs((group.last_modified_date-item.last_modified_date)* 24 * 60 * 60)<组中选择coun(*)。 4
但是循环很慢。有没有办法通过单个查询将日期插入到组表中?子查询很好,我的目标是删除循环。
通过last_modified_date从项目组中选择last_modified_date,但也将彼此靠近的日期分组。
答案 0 :(得分:3)
您可以使用的一个技巧是使用分析函数将记录分配给组。您可以将lag
与case
结合使用来标记组中的第一个“成员” - 即前一行的日期超过当前行日期之前的N秒(我是这里选择N = 5)。然后,新组的所有开始时间都是标记的记录:
with groups as (
select
auto_increment,
last_modified_date,
case when last_modified_date -
lag(last_modified_date, 1, date '1900-01-01')
over (order by last_modified_date) < (1 / 24 / 60 * 5) then 1 else 0
end as starts_new_group
from your_table
)
select
auto_increment,
last_modified_date
where
starts_new_group = 1;
NB我没有测试这段代码!如果你可以用数据创建一个SQL小提琴,我可以在必要时调试查询。
答案 1 :(得分:0)
您可以通过分组的cte创建驱动程序表,然后JOIN
使用BETWEEN
创建一个驱动程序表。我不知道oracle语法,但这适用于SQL Server,所以希望你可以适应它:
DECLARE @begindate DATETIME = (SELECT MIN(last_modified_date) FROM #Table1)
,@enddate DATETIME = (SELECT MAX(last_modified_date) FROM #Table1)
;WITH cte AS (SELECT @begindate AS group_beg
,DATEADD(second,3,@begindate) AS group_end
, 1 AS Group_
UNION ALL
SELECT DATEADD(second,4,group_beg)
, DATEADD(second,7,group_beg)
, Group_ + 1
FROM cte
WHERE group_beg < @enddate
)
SELECT a.*,DENSE_RANK() OVER(ORDER BY b.Group_)
FROM #Table1 a
JOIN cte b
ON a.last_modified_date BETWEEN b.group_beg AND b.group_end
OPTION (MAXRECURSION 0)