我脑海中浮现出一些有趣的东西。假设我们有一个表(在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<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;
}
}
它有效,但有些“不是非常有效”。是否有“更智能”的方式,例如T-SQL查询或其他算法来执行此操作?
答案 0 :(得分:2)
您可以使用CTE(Common Table Expressions)来实现此目的。
下面的查询适用于SQL Server的Adventure Works演示表(“速度限制”为7)。
受到关于SO的另一个问题的强烈启发:GROUP BY for continuous rows in SQL。
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
<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
答案 1 :(得分:1)
简单,或者可以吗?
SELECT
Location,
Velocity,
Time,
CASE WHEN Velocity > @SpeedBarrier THEN 1 ELSE 0 END AS IsOverSpeed
FROM
SpeedTable
答案 2 :(得分:1)
我使用以下部分来获取一些数据(我在兼容模式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
答案 3 :(得分:-1)
假设如果它匹配,那么将遵循以下SQL查询
选择 位置,速度,时间, (速度&gt; speedLimit =真或速度&lt; = speedLimit =假)超速 从 表 哪里 speedLimit = yourGivenLimit
我没有对此进行测试,但我确信会有类似的事情。