简体   繁体   English

找到超速的时期?

[英]Find the period of over speed?

Just something interesting come in my mind. 我脑海里浮现出一些有趣的东西。 Assume that we have a table (in SQL Server) like this: 假设我们有一个表(在SQL Server中),如下所示:

  • Location 位置
  • Velocity 速度
  • Time 时间

for example: 例如:

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

Assume that speed barrier is 40kph, the output is something like this 假设速度障碍是40kph,输出是这样的

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

What is the best way to determine over speed periods (speed barrier is defined) ? 确定超速时间的最佳方法是什么(定义了速度障碍)? My first idea was loading the table into an array, and then iterate over array to find these periods: 我的第一个想法是将表加载到一个数组中,然后遍历数组以查找这些句点:

(Pseudo C# code) (伪C#代码)

bool isOverSpeed = false;

for (int i =0;i<arr.Length;i++)
{
if (!isOverSpeed)
    if (arr[i].Velocity > 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;
          }

}

It works, but somewhat "not very effectively". 它有效,但有点“不太有效”。 Is there a "smarter" way, such as a T-SQL query or another algorithm to do this? 是否有“更智能”的方式,例如T-SQL查询或其他算法来执行此操作?

You can achieve this by using CTE ( Common Table Expressions ). 您可以使用CTE( 公用表表达式 )来实现此目的。

The query below works against the Adventure Works demo table of SQL Server (the "speed limit" being 7). 下面的查询适用于SQL Server的Adventure Works演示表(“速度限制”为7)。

This is strongly inspired by another question on SO: GROUP BY for continuous rows in SQL . 受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

Something along these lines should suit you: 这些方面的东西应该适合你:

with CTE as (
    select
        ROW_NUMBER() over(order by [Time]) as RowNo
        , *
    from
        <table_name>
)
, MySpeedGroup as (
    select
        s.*
        ,(select
              max([Time])
          from
              CTE c
          where
              not exists (select * from CTE
                              where RowNo = c.RowNo-1
                              and Velocity > <speed_limit>
                              and c.Velocity > <speed_limit>)
              and c.[Time] <= s.[Time]) as GroupID
    from
        <table_name> 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) > <speed_limit>
order by
    minimum

It can't be that simple, or can it? 它不能那么简单,还是可以呢?

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

I've used the following part to get some data ( I'm on compatibility mode 80 atm so I don't have a time field and am using an INT for the timestamp) 我已经使用以下部分来获取一些数据(我在兼容模式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);

Assuming your Location are fixed points that has to be passed in order to complete the following will produce the desired output. 假设您的位置是必须通过的固定点,以便完成以下操作将产生所需的输出。 I've broken it out into multiple Stages so as to make it clear what each part does. 我已将其分解为多个阶段,以便明确每个部分的作用。

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

Assuming that if it matches it will be false follow the below SQL query 假设如果它匹配则将为false,请遵循以下SQL查询

select location, velocity, time, (velocity > speedLimit = true OR velocity <= speedLimit = false) as overspeed from table where speedLimit = yourGivenLimit 选择位置,速度,时间,(速度> speedLimit = true或者速度<= speedLimit = false)从表中超速,其中speedLimit = yourGivenLimit

I did not test this but I am sure something like it will do. 我没有对此进行测试,但我相信它会做的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM