Jef*_*sen 6 sql sql-server datetime timespan
我有一个带有两个日期时间字段(CnxStartdatetime,CnxEnddatetime)的SQL Server表.每行代表信息的传输. 我试图找到基于这两个时间戳的最大并发传输数.我有一个工作查询,但它既缓慢又非常麻烦.我知道必须有一个更好的方法来解决这个问题,但不能提出任何问题.
对于当前版本,如果我以5"级别"运行并获得结果,我必须返回并添加大量SQL来测试是否存在6个并发传输的实例,等等.一旦查询获得7-8"级别"它变得非常慢.
当前版本的片段:
select
t1.id, t2.id, t3.id, t4.id, t5.id, t6.id, t7.id, t8.id, t9.id, t10.id
FROM
dbo.MyTable t1, dbo.MyTable t2, dbo.MyTable t3, dbo.MyTable t4, dbo.MyTable t5,
dbo.MyTable t6, dbo.MyTable t7, dbo.MyTable t8, dbo.MyTable t9, dbo.MyTable t10
WHERE
(((t2.cnxstartdatetime >= t1.cnxstartdatetime) and (t2.cnxstartdatetime <= t1.cnxenddatetime))
or ((t2.cnxenddatetime >= t1.cnxstartdatetime) and (t2.cnxenddatetime <= t1.cnxenddatetime)))
AND
t2.id != t1.id
AND
(((t3.cnxstartdatetime >= t2.cnxstartdatetime) and (t3.cnxstartdatetime >= t1.cnxstartdatetime)and (t3.cnxstartdatetime <= t1.cnxenddatetime) and (t3.cnxstartdatetime <= t2.cnxenddatetime))
or ((t3.cnxenddatetime >= t2.cnxstartdatetime) and (t3.cnxenddatetime >= t1.cnxstartdatetime)and (t3.cnxenddatetime <= t1.cnxenddatetime) and (t3.cnxenddatetime <= t2.cnxenddatetime)))
AND
t3.id != t2.id AND t3.id != t1.id
AND
(((t4.cnxstartdatetime >= t3.cnxstartdatetime) and (t4.cnxstartdatetime >= t1.cnxstartdatetime)and (t4.cnxstartdatetime >= t2.cnxstartdatetime) and (t4.cnxstartdatetime <= t1.cnxenddatetime) and (t4.cnxstartdatetime <= t3.cnxenddatetime)and (t4.cnxstartdatetime <= t2.cnxenddatetime))
or ((t4.cnxenddatetime >= t3.cnxstartdatetime) and (t4.cnxenddatetime >= t1.cnxstartdatetime)and (t4.cnxenddatetime >= t2.cnxstartdatetime) and (t4.cnxenddatetime <= t1.cnxenddatetime)and (t4.cnxenddatetime <= t3.cnxenddatetime)and (t4.cnxenddatetime <= t2.cnxenddatetime)))
AND
t4.id != t3.id AND t4.id != t2.id AND t4.id != t1.id
... *snip*
Run Code Online (Sandbox Code Playgroud)
编辑许多回复建议我使用cross join.这并没有达到我想要的结果.这是cross join一个记录的"重叠" 结果的一个例子.这是它给我的ID列表中11787 你可以看到,11781并没有重叠,11774 这是一个简单,其时间跨度相交的任何记录列表11787
11774 2011-04-29 01:02:56.780 2011-04-29 01:02:58.793
11777 2011-04-29 01:02:56.780 2011-04-29 01:02:58.843
11778 2011-04-29 01:02:56.780 2011-04-29 01:02:58.950
11775 2011-04-29 01:02:56.793 2011-04-29 01:02:58.843
11776 2011-04-29 01:02:56.793 2011-04-29 01:02:58.890
11780 2011-04-29 01:02:58.310 2011-04-29 01:03:02.687
11779 2011-04-29 01:02:58.327 2011-04-29 01:03:02.543
11787 2011-04-29 01:02:58.530 2011-04-29 01:03:08.827 **
11781 2011-04-29 01:02:59.030 2011-04-29 01:03:05.187
11782 2011-04-29 01:02:59.247 2011-04-29 01:03:05.467
11784 2011-04-29 01:02:59.293 2011-04-29 01:03:05.810
11791 2011-04-29 01:03:00.107 2011-04-29 01:03:13.623
11786 2011-04-29 01:03:00.843 2011-04-29 01:03:08.983
11783 2011-04-29 01:03:02.560 2011-04-29 01:03:05.793
11785 2011-04-29 01:03:02.717 2011-04-29 01:03:07.357
11790 2011-04-29 01:03:05.200 2011-04-29 01:03:14.153
11804 2011-04-29 01:03:05.687 2011-04-29 01:03:25.577
11811 2011-04-29 01:03:07.093 2011-04-29 01:03:35.153
11799 2011-04-29 01:03:07.123 2011-04-29 01:03:24.437
11789 2011-04-29 01:03:08.793 2011-04-29 01:03:13.577
Run Code Online (Sandbox Code Playgroud)
我也尝试用递归编写CTE,但我无法弄清楚如何确保当前与当前并发堆栈中的ID任何一个都不匹配ID.下面只是自我解决,直到达到极限.
WITH TransmissionConcurrency (StartTime, EndTime, ConcurrencyLevel) AS
(
SELECT
CnxStartDatetime AS StartTime,
CnxEndDatetime AS EndTime,
1 AS ConcurrencyLevel
FROM dbo.MyTable
UNION ALL
SELECT
CASE WHEN d.CnxStartDatetime > tc.StartTime THEN d.CnxStartDatetime ELSE tc.StartTime END AS StartTime,
CASE WHEN d.CnxEndDatetime < tc.EndTime THEN d.CnxEndDatetime ELSE tc.EndTime END AS EndDate,
tc.ConcurrencyLevel + 1 as ConcurrencyLevel
FROM dbo.MyTable d
INNER JOIN TransmissionConcurrency tc ON
((d.CnxStartDatetime between tc.StartTime and tc.EndTime)
or
(d.CnxEndDatetime between tc.StartTime and tc.EndTime)
or
(d.CnxStartDatetime <= tc.StartTime and d.CnxEndDatetime >= tc.EndTime))
)
SELECT *
FROM TransmissionConcurrency
ORDER BY ConcurrencyLevel, StartTime, EndTime
Run Code Online (Sandbox Code Playgroud)
我想出了下面的图表,试图更好地解释我在寻找什么.
A [--------]
B [-----]
C [------]
D [---]
E [---]
F [-]
Run Code Online (Sandbox Code Playgroud)
在这个例子中,cross join方法会告诉我最大并发数A为6(Awith B, C, D, E and F)我正在寻找的最大并发数为3(A有B,F 或 A有C,E)
杰夫. 我曾经写过一个类似的查询 - 但在 Oracle 中 - 不确定这是否适用于 SQL-Server,但值得尝试:也许它会给你一些想法:
select
t.time as b,
lead(t.time) over (order by t.time, t.weight desc) as e,
sum(t.weight) over (order by t.time, t.weight desc) as cnt
from
( select trunc(:aStartWith) as time, 0 as weight from dual
union all
select req_recieved as time, +1 as weight
from log_tbl
where trunc(req_recieved, 'mi') between :aStartWith - interval '10' minute and :aEndWith + interval '10' minute
union all
select response_sent as time, -1 as weight
from log_tbl
where trunc(req_recieved, 'mi') between :aStartWith - interval '10' minute and :aEndWith + interval '10' minute
union all
select trunc(:aEndWith) as time, 0 as weight from dual
) t
Run Code Online (Sandbox Code Playgroud)
总体思路是,我遍历:aStartWith日期和:aEndWith日期之间的所有请求,为给定时间段内开始的每个请求分配 +1 权重部分,为同一时间段内结束的每个请求分配 -1 权重部分。
这里我假设请求不再是那10分钟(where trunc(req_recieved, 'mi') between :aStartWith - interval '10' minute and :aEndWith + interval '10' minute);和select ... from dual是边界条件。
然后,通过分析函数,我找到请求的结束时间 ( ) 并对当前请求的权重求和 - 这将给出从时间 ( )开始到时间( ) 结束lead(t.time) over (order by t.time, t.weight desc) as e的多个请求。besum(t.weight) over (order by t.time, t.weight desc) as cnt
要找到最大请求数,您只需用所需的评估包装此查询即可。
您可以尝试一下这个场景是否适合您吗?希望如此:)
| 归档时间: |
|
| 查看次数: |
3993 次 |
| 最近记录: |