SQL汇总时间范围的最小/最大活动值
这是一个SQL问题,我无法在一个简单的查询中解决它。有可能吗 数据集为(添加字母以便于理解): 所需输出为:SQL汇总时间范围的最小/最大活动值,sql,Sql,这是一个SQL问题,我无法在一个简单的查询中解决它。有可能吗 数据集为(添加字母以便于理解): 所需输出为: PeriodStart New ActiveAtEnd MinActive MaxActive 09:50 0 0 0 0 10:00 3 (ABC) 2 (AC) 0 3 (ABC) 10:10 1 (D)
PeriodStart New ActiveAtEnd MinActive MaxActive
09:50 0 0 0 0
10:00 3 (ABC) 2 (AC) 0 3 (ABC)
10:10 1 (D) 2 (CD) 1 (C) 2 (AC or CD)
10:20 0 1 (D) 1 (C) 2 (CD)
10:30 1 (E) 1 (D) 1 (D) 2 (DE)
10:40 0 0 0 1 (D)
10:50 0 0 0 0
因此,需要的查询是第一个表的摘要,计算10分钟内第一个表的最小重叠时间段(开始-结束)和最大重叠时间段(开始-结束)
“New”是汇总期间中以开头的行数ActiveAtEnd'是汇总期间结束时活动的行数
我正在使用Oracle,但我相信解决方案是可以调整的。不允许使用存储过程-只需简单地选择/插入(允许使用视图)。每10分钟输出运行一个SQL命令也可以(一旦填充,它将保持最新状态)
感谢您提出的任何想法,包括“不可能”;-)新的和活动的结束非常简单(假设期间的开始和结束存储在临时变量中):
选择@periodStart periodStart
,@periodEnd periodEnd
,n.[新]
,ae.ActiveAtEnd
从(
选择计数(*)[新建]
来自@times
其中[start]>=@periodStart
和[开始]<@PeriodEnd
)n
交叉连接
(
选择计数(*)[ActiveAtEnd]
来自@times
何处[开始]<@PeriodEnd
和[结束]>=@PeriodEnd
)ae
最大和最小活动更难。您可以假定一分钟的粒度,因此您需要在该粒度上分解活动周期,以便能够探测每个切片
我不确定一次查询就可以做到这一点 我能解决这类问题的唯一方法就是计算每一分钟的“开始”次数。然后获得10分钟组的最大值(或最小值)。我无法应用基于集合的方法。我正在努力处理ActiveAtEnd值,但其他的都可以 这是针对MySQL的:
set @active:=0;
select
period,
sum( if( score=1, 1, 0)) New,
if( max(ab) > max(aa), max(ab), max(aa)) MaxActive,
if( min( ab ) < min( aa ), min(ab), min(aa)) MinActive
from (
select
period,
etime,
score,
@active ab,
@active:=@active+score aa
from (
select
from_unixtime( floor( unix_timestamp(start)/600) * 600) period,
start etime,
+1 score
from ev
union all
select from_unixtime( floor( unix_timestamp(end)/600) * 600) period,
end etime,
-1 score
from ev
) event order by etime
) as temp
group by period;
假设您还有(或创建)一个名为@Times的表,每十分钟的开始时间有一条记录,
那么
Select T.Start,
(Select Count(*) From testTab
Where Start Between T.Start
And DateAdd(minute, 10, T.Start)) New,
(Select Count(*) From testTab
Where Start < DateAdd(minute, 10, T.Start)
And EndDt > DateAdd(minute, 10, T.Start)) ActiveAtEnd,
(Select Max(Cnt) From
(Select Count(Distinct T.Which) Cnt
From (Select Distinct Start
From testTab
Where Start Between T.Start
And DateAdd(minute, 10, T.Start)
Union Select T.Start
Union Select DateAdd(minute, 10, T.Start)) Z
Left Join testTab T
On Z.Start Between T.Start And T.EndDt
Group By Z.Start) ZZ ) MaxActive,
(Select Min(Cnt) From
(Select Count(Distinct T.Which) Cnt
From (Select Distinct Start
From testTab
Where Start Between T.Start
And DateAdd(minute, 10, T.Start)
Union Select T.Start
Union Select DateAdd(minute, 10, T.Start)) Z
Left Join testTab T
On Z.Start Between T.Start And T.EndDt
Group By Z.Start) ZZ ) MinActive
From @Times T
警告:聚合或其他集合操作会消除空值。起始和结束列是什么类型的?它们是date还是varchar2?它们是现实生活中的时间戳——我简化了这个问题
set @active:=0;
select
period,
sum( if( score=1, 1, 0)) New,
if( max(ab) > max(aa), max(ab), max(aa)) MaxActive,
if( min( ab ) < min( aa ), min(ab), min(aa)) MinActive
from (
select
period,
etime,
score,
@active ab,
@active:=@active+score aa
from (
select
from_unixtime( floor( unix_timestamp(start)/600) * 600) period,
start etime,
+1 score
from ev
union all
select from_unixtime( floor( unix_timestamp(end)/600) * 600) period,
end etime,
-1 score
from ev
) event order by etime
) as temp
group by period;
+---------------------+------+-----------+-----------+
| period | New | MaxActive | MinActive |
+---------------------+------+-----------+-----------+
| 2008-11-19 10:00:00 | 3 | 3 | 0 |
| 2008-11-19 10:10:00 | 1 | 2 | 1 |
| 2008-11-19 10:20:00 | 0 | 2 | 1 |
| 2008-11-19 10:30:00 | 1 | 2 | 1 |
| 2008-11-19 10:40:00 | 0 | 1 | 0 |
+---------------------+------+-----------+-----------+
Select T.Start,
(Select Count(*) From testTab
Where Start Between T.Start
And DateAdd(minute, 10, T.Start)) New,
(Select Count(*) From testTab
Where Start < DateAdd(minute, 10, T.Start)
And EndDt > DateAdd(minute, 10, T.Start)) ActiveAtEnd,
(Select Max(Cnt) From
(Select Count(Distinct T.Which) Cnt
From (Select Distinct Start
From testTab
Where Start Between T.Start
And DateAdd(minute, 10, T.Start)
Union Select T.Start
Union Select DateAdd(minute, 10, T.Start)) Z
Left Join testTab T
On Z.Start Between T.Start And T.EndDt
Group By Z.Start) ZZ ) MaxActive,
(Select Min(Cnt) From
(Select Count(Distinct T.Which) Cnt
From (Select Distinct Start
From testTab
Where Start Between T.Start
And DateAdd(minute, 10, T.Start)
Union Select T.Start
Union Select DateAdd(minute, 10, T.Start)) Z
Left Join testTab T
On Z.Start Between T.Start And T.EndDt
Group By Z.Start) ZZ ) MinActive
From @Times T
Declare @Times Table (Start datetime Primary key Not Null)
Declare @Start DateTime
Set @Start = '1 Nov 2008 10:00'
While @Start < '1 Nov 2008 11:00' begin
Insert @Times(Start) values(@Start)
Set @Start = DateAdd(minute, 10, @Start)
End
start endDt Which
----------------------- ----------------------- -----
2008-11-01 10:01:00.000 2008-11-01 10:12:00.000 A
2008-11-01 10:03:00.000 2008-11-01 10:06:00.000 B
2008-11-01 10:05:00.000 2008-11-01 10:25:00.000 C
2008-11-01 10:14:00.000 2008-11-01 10:42:00.000 D
2008-11-01 10:32:00.000 2008-11-01 10:36:00.000 E
2008-11-01 10:22:00.000 2008-11-01 10:51:00.000 F
2008-11-01 10:22:00.000 2008-11-01 10:23:00.000 G
Start New ActiveAtEnd MaxActive MinActive
----------------------- ----------- ----------- ----------- -----------
2008-11-01 10:00:00.000 3 2 3 0
2008-11-01 10:10:00.000 1 2 2 2
2008-11-01 10:20:00.000 2 2 4 2
2008-11-01 10:30:00.000 1 2 3 2
2008-11-01 10:40:00.000 0 1 2 1
2008-11-01 10:50:00.000 0 0 1 0