找到超速的时期?

我脑海里浮现出一些有趣的东西。 假设我们有一个表(在SQL Server中),如下所示:

  • 地点
  • 速度
  • 时间

例如:

Location Velocity Time 1 40 1:20 2 35 2:00 3 45 2:05 4 50 2:30 5 60 2:45 6 48 2:55 7 40 3:00 8 35 3:15 9 50 3:20 10 70 3:30 11 50 3:35 12 40 3:40 

假设速度障碍是40kph,输出是这样的

 Starttime Endtime 2:05 3:00 3:20 3:35 

确定超速时间的最佳方法是什么(定义了速度障碍)? 我的第一个想法是将表加载到数组中,然后迭代数组以查找这些句点:

(伪C#代码)

 bool isOverSpeed = false; for (int i =0;i speedBarrier) { #insert the first record into another array. isOverSpeed = true; } if(isOverSpeed) if (arr[i].Velocity < speedBarrier) { #insert the record into that array isOverSpeed = false; } } 

它有效,但有点“不太有效”。 是否有“更智能”的方式,例如T-SQL查询或其他算法来执行此操作?

您可以使用CTE( 公用表表达式 )来实现此目的。

下面的查询适用于SQL Server的Adventure Works演示表(“速度限制”为7)。

这受到另一个关于SO的问题的强烈启发: 对于SQL中的连续行,GROUP BY 。

 with CTE as ( select ROW_NUMBER() over(order by SalesTaxRateID) as RowNo , * from Sales.SalesTaxRate ) , MyLogGroup as ( select l.* ,(select max(SalesTaxRateID) from CTE c where not exists (select * from CTE where RowNo = c.RowNo-1 and TaxRate > 7 and c.TaxRate > 7) and c.SalesTaxRateID <= l.SalesTaxRateID) as GroupID from Sales.SalesTaxRate l) select min(SalesTaxRateID) as minimum , max(SalesTaxRateID) as maximum , avg(TaxRate) from MyLogGroup group by GroupID having min(TaxRate) > 7 order by minimum 

沿着这些方向的东西应该适合你:

 with CTE as ( select ROW_NUMBER() over(order by [Time]) as RowNo , * from  ) , MySpeedGroup as ( select s.* ,(select max([Time]) from CTE c where not exists (select * from CTE where RowNo = c.RowNo-1 and Velocity >  and c.Velocity > ) and c.[Time] <= s.[Time]) as GroupID from  l) select min([Time]) as minimum , max([Time]) as maximum , avg([Velocity]) -- don't know if you want this from MySpeedGroup group by GroupID having min(Velocity) >  order by minimum 

它不能那么简单,还是可以呢?

 SELECT Location, Velocity, Time, CASE WHEN Velocity > @SpeedBarrier THEN 1 ELSE 0 END AS IsOverSpeed FROM SpeedTable 

我已经使用以下部分来获取一些数据(我在兼容模式80 atm所以我没有时间字段并且使用INT作为时间戳)

 DECLARE @Info TABLE (Location INT IDENTITY, Velocity INT, [Time] INT); INSERT INTO @Info (Velocity, [Time]) VALUES (40, 80); INSERT INTO @Info (Velocity, [Time]) VALUES (35, 120); INSERT INTO @Info (Velocity, [Time]) VALUES (45, 125); INSERT INTO @Info (Velocity, [Time]) VALUES (50, 150); INSERT INTO @Info (Velocity, [Time]) VALUES (60, 165); INSERT INTO @Info (Velocity, [Time]) VALUES (48, 175); INSERT INTO @Info (Velocity, [Time]) VALUES (40, 180); INSERT INTO @Info (Velocity, [Time]) VALUES (35, 195); INSERT INTO @Info (Velocity, [Time]) VALUES (50, 200); INSERT INTO @Info (Velocity, [Time]) VALUES (70, 210); INSERT INTO @Info (Velocity, [Time]) VALUES (50, 215); INSERT INTO @Info (Velocity, [Time]) VALUES (40, 220); INSERT INTO @Info (Velocity, [Time]) VALUES (45, 225); INSERT INTO @Info (Velocity, [Time]) VALUES (45, 230); 

假设您的位置是必须通过的固定点,以便完成以下操作将产生所需的输出。 我已将其分解为多个阶段,以便明确每个部分的作用。

 DECLARE @Limit INT; SET @Limit = 40; WITH Stage1 ([Location], [Velocity], [Time]) AS ( SELECT * FROM @Info WHERE [Velocity] > @Limit ), Stage2 (Start) AS ( SELECT [Time] FROM [Stage1] WHERE ([Location] - 1) NOT IN (SELECT [Location] FROM [Stage1]) ), Stage3 ([Start], [Stop]) AS ( SELECT [Start] , (SELECT MIN([Time]) FROM [Stage1] WHERE ([Location] + 1) NOT IN (SELECT [Location] FROM [Stage1]) AND [Time] > [Stage2].[Start]) FROM Stage2 ) SELECT * FROM Stage3 

假设如果它匹配,那么将遵循以下SQL查询

选择位置,速度,时间,(速度> speedLimit = true或者速度<= speedLimit = false)从表中超速,其中speedLimit = yourGivenLimit

我没有测试过这个,但我确信它会做的事情。