【问题标题】:Index query for large data in SQL ServerSQL Server 中大数据的索引查询
【发布时间】:2019-12-12 03:36:44
【问题描述】:

我正在使用 SQL Server 在 VB.net 中处理一些流量数据。我的表名是[Sim VehRecord],列是:

Record ID
Simulation Sec(s)
Vehicle No
Link No
Lane No
Position (m)
Speed (km/hr)

根据第 2、3 和 6 列,我想为每一行填写第 7 列。

此处显示的流量数据示例:

Record ID     Sim Sec(s)  Vehicle No Link No Lane No Position(m)  Speed (km/hr)  
-------------------------------------------------------------------------------
        1        0.80        2        74        1        13.42    
        2        0.80        3        74        2        12.88    
        3        0.80        4        2         1        2.90    
        4        1.00        1        73        1        17.97  
        5        1.00        2        74        1        17.73  
        6        1.00        3        74        2        17.22  
        7        1.00        4        2         1        7.22  
        8        1.20        1        73        1        22.42  
        9        1.20        2        74        1        22.04  
        10       1.20        3        74        2        21.57  
        11       1.20        4        2         1        11.54  

我使用了以下代码:

CREATE CLUSTERED INDEX IX_SimVehRecord_VehNo
ON [Sim VehRecord] ([Sim Time (sec)] ASC, [Position (m)] ASC)

UPDATE [Sim VehRecord]
SET [Speed (km/hr)] = (SELECT CONVERT(DECIMAL(7, 2), 3.6 * COALESCE (([Sim VehRecord].[Position (m)] - (SELECT TOP 1 sv.[Position (m)])) / NULLIF(([Sim VehRecord].[Sim Time (sec)] - sv.[Sim Time (sec)]), 0), 0)) 
                       FROM [Sim VehRecord] sv 
                       WHERE sv.[Veh No] = [Sim VehRecord].[Veh No]
                         AND sv.[Position (m)] < [Sim VehRecord].[Position (m)]
                         AND sv.[Sim Time (sec)] < [Sim VehRecord].[Sim Time (sec)])

但我总是得到一个错误:

子查询返回超过 1 个值。

我们将不胜感激。

问候。

【问题讨论】:

  • 错误很明显...您在更新语句中使用的子查询返回多行并且您更新集合子句期望返回 1 行。可以单独运行select语句查看结果

标签: sql-server vb.net


【解决方案1】:

您的查询实际上在 8、9、10、11 中返回多个结果。

你需要车辆的位置和之前的位置来计算速度,对吧?

所以我相信你需要类似的东西

with yourTable as (select * 
from (
values (1, 0.80, 2, 74,  1, 13.42),
(2, 0.80, 3, 74,  2, 12.88),
(3, 0.80, 4, 2,   1, 2.90),
(4, 1.00, 1, 73,  1, 17.97),
(5, 1.00, 2, 74,  1, 17.73),
(6, 1.00, 3, 74,  2, 17.22),
(7, 1.00, 4, 2,   1, 7.22),
(8, 1.20, 1, 73,  1, 22.42),
(9, 1.20, 2, 74,  1, 22.04),
(1, 1.20, 3, 74,  2, 21.57),
(1, 1.20, 4, 2,   1, 11.54)
) V (ID, Sec, Vehicle, Link, Lane, Position)),

pos_and_previous_pos as (
select 
Vehicle, Lane,ID, Sec, Position, 
LAG(Position) over (partition by Vehicle, lane order by sec asc) as previous_pos,
LAG(Sec) over (partition by Vehicle, lane order by sec asc) as previous_sec
from yourTable
)

select id, vehicle, sec, position, 3.6 * isnull((Position - previous_pos) / (Sec - previous_sec), 0) kmh
from pos_and_previous_pos
order by vehicle, lane, sec

我也按车道进行了分区,我不确定它在您的用例中是否重要。

在此处查看工作演示:

https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=fdc5982119a56cd6730635f076c286bc

我猜你的更新会是这样的

with SimVehRecord as (
select 
[Record ID], [Simulation Sec(s)], [Position (m)], 
LAG([Position (m)]) over (partition by [Vehicle No]  order by [Simulation Sec(s)] asc) as previous_pos,
LAG([Simulation Sec(s)]) over (partition by [Vehicle No] order by [Simulation Sec(s)] asc) as previous_sec
from [Sim VehRecord]
)
select *, (3.6 * isnull(([Position (m)] - previous_pos) / ([Simulation Sec(s)] - previous_sec), 0)) as kmh from SimVehRecord;

工作小提琴更新示例:

https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=ee0c496d930117d632f96fd26440a435

一定要有索引 [车号]、[模拟段]、[位置(m)]

如果对你有帮助,请告诉我..

【讨论】:

  • 感谢 Frederic.. 我花了很长时间来理解逻辑。请注意,我更加强调处理时间。因为,我有将近 500 万条数据。以前我应用了递归逻辑,它过去需要将近 8 分钟的时间来处理。根据您的指导,我提出了以下解决方案:
  • ``` UPDATE [Sim VehRecord] SET [Speed (km/hr)] = (SELECT FORMAT(3.6* COALESCE (([Sim VehRecord].[Position (m)] - LAG (sv .[Position (m)],1,0) OVER (PARTITION BY sv.[Veh No] ORDER By sv.[Sim Time (sec)] ASC))/NULLIF(([Sim VehRecord].[Sim Time (sec) )] - LAG (sv.[Sim Time (sec)],1,0) OVER (PARTITION BY sv.[Veh No] ORDER By sv.[Sim Time (sec)] ASC)),0),0), 'N2','en-us') 来自 [Sim VehRecord] sv 其中 sv.[Veh No] = [Sim VehRecord].[Veh No] And sv.[Position (m)]
  • @Tariq 看到这个小提琴dbfiddle.uk/… 一个表中的工作更新,其名称和列与您的相似(抱歉更新了分区中没有通道的小提琴)
  • 我的更新是错误的确实错过了 from .... inner join to_cte ...抱歉我在写答案时困了
  • @Tariq,您是否已经拥有包含 [vehicle no]、[sim time(sec)]、[position (m)] 列的索引,对吗?
猜你喜欢
  • 1970-01-01
  • 2012-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-25
相关资源
最近更新 更多