I have a SQL Server table with two datetime fields ( CnxStartdatetime , CnxEnddatetime ). Each line represents the transmission of information. I am trying to find the maximum number of concurrent transfers based on these two timestamps . I have a working request, but it is slow and extremely cumbersome. I know that there must be a better way to do this, but cannot come up with.
For the current version, if I run it with 5 levels and get the results, I need to go back and add a ton of SQL to check if there are instances of 6 simultaneous transfers, etc. As soon as the request receives 7-8 βlevelsβ in depth, it becomes very slow.
Fragment of the current version:
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*
Change Many answers show that I am using cross join . This does not lead to the results that I am looking for. Here's an example of cross join results for one record "overlapping". This is the list that he gives me for ID 11787 As you can see, 11781 does not overlap 11774 This is just a list of any record whose time interval intersects 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
I also tried writing a CTE with recursion, but I cannot figure out how to ensure that the current ID does not match the previous ID in the current concurrency stack. The following is simply repeated on its own until it reaches the limit.
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
I came up with the diagram below to better explain what I'm looking for.
A [--------] B [-----] C [------] D [---] E [---] F [-]
In this case, the cross join methods will tell me that the maximum concurrency with A is 6 ( A with B, C, D, E and F ). What I'm looking for will be max concurrency of 3 ( A with B,F or A with C,E )