C# T-SQL快进游标与foreach

C# T-SQL快进游标与foreach,c#,sql-server,tsql,C#,Sql Server,Tsql,我想计算gps点之间的距离,以获得第一个点和最后一个点之间的完整距离 我的问题是:什么更快 将所有行加载到数据表中,然后 通过foreach在c#net中计算它 或 在Sql Server上使用 使用快进存储过程 光标 我说的大约有400000行。如果您使用的是SQL Server 2008,我建议尝试将它们存储为地理类型,然后 declare @point1 geography = 'POINT (-42 84)'; declare @point2 geography = 'POINT (

我想计算gps点之间的距离,以获得第一个点和最后一个点之间的完整距离

我的问题是:什么更快

  • 将所有行加载到数据表中,然后 通过foreach在c#net中计算它 或
  • 在Sql Server上使用 使用快进存储过程 光标

我说的大约有400000行。

如果您使用的是SQL Server 2008,我建议尝试将它们存储为
地理类型,然后

declare @point1 geography = 'POINT (-42 84)';
declare @point2 geography = 'POINT (-3 10)';
select @point1.STDistance (@point2)

但要想真正知道什么是最快的,你必须同时尝试这两种方法。

我肯定会在服务器上尝试这样做-尽量避免仅仅为了计算一个数字(最终)而拖拽40万行

另外:如果可能的话,我会尝试在没有光标的情况下进行。游标在SQL Server上是一场噩梦-应该不惜一切代价避免它们

在您的情况下-不知道详细的表结构-您肯定可以这样做,例如,递归CTE(公共表表达式),从第一个元素开始,总距离为0.0,然后递归地求和所有其他路径点,计算点(x+1)和点x之间的距离,并求和到之前的总距离

最后,您应该有一个CTE,它显示所有路径点、任意两个路径点之间的所有距离以及整个旅程的总距离

该CTE将类似于:

;WITH Waypoints AS
(
    -- anchor your query
    SELECT
       WaypointID, PrevWaypointID, Long, Lat, 0.0 as Distance, 0.0 as SumOfDistance
    FROM
       dbo.Waypoint
    WHERE
       PrevWaypointID IS NULL  --  or some other condition

    UNION  -- recurse

    SELECT
       WaypointID, Long, Lat, 
       dbo.GetDistanceBetween(wp.WaypointID, pts.WaypointID),   -- distance
       pts.SumOfDistance + dbo.GetDistanceBetween(wp.WaypointID, pts.WaypointID)  -- sum
    FROM
       dbo.Waypoint wp
    INNER JOIN
       Waypoints pts ON wp.PrevWaypointID = pts.WaypointID          
    WHERE
       (some condition; ID = 1 or PreviousWaypointID IS NULL or something)
)
SELECT * FROM Waypoints

我的理解是,即使在SQL中使用游标,它仍然比在前端代码中迭代快几个数量级。当时,ADO和DAO是有争议的技术,因此随着ADO.NET和数据集的出现,情况可能会发生一些变化

然而,我敢打赌,专门为这类事情设计的T-SQL仍然更高效

如果您在迭代过程中需要应用特殊逻辑,则可能会出现例外,但我认为在后端执行计算的正确设置的SQL游标将优于数据集


最好的方法是不使用SQL中的游标,如果您能够

如果您使用的是Sql Server 2008(或更新版本),那么您可以使用地理类型在服务器上执行所有操作。下面是一个用于计算两点之间距离的示例:

SELECT geography::Point(lat1, lon1, 4326).STDistance(geography::Point(lat2, lon2, 4326))
我不确定这是否可以在没有光标的情况下使用,但是可能

如果您使用的是较旧版本的SQL Server,那么您仍然可以将距离公式作为存储过程自己编写,并在服务器端执行所有操作


将整个数据集下载到客户端并在客户端执行所有计算几乎肯定需要更长的时间,因为下载时间将比计算时间长得多。

最快的方法是在服务器上计算数据,但是没有光标……@marc_s:有没有办法在没有光标的情况下为每一行添加一个距离?请看我的回答-你没有给我们提供很多细节,所以我只能提供一个非常笼统的想法……你需要计算一个运行总数还是一个汇总数字?如果它是一个正在运行的总计,那么使用CLR可以为您提供一种超快速游标,其性能超过基于集合的方法。鉴于SQL Server中
OVER
子句的当前有限实现,在某些情况下,最好的方法可能是将所有行加载到本地计算机上,并保留其缓存副本,只是偶尔联系服务器获取其数据的更新副本。我正在发布,而其他人给出了更好的答案。订单在哪里?或者我错过了什么吗?@Jonas Elfström:不需要订单-有一行是锚,从那时起,它总是一个
SomeRow.PrevWaypointID=previousRow.WaypointID
连接-订单是由一个航路点和它的上一个航路点之间的关系定义的。啊,错过了链表结构。这是正确的,这是唯一适用的,如果你有一个最大的100分?如果我用超过100点的分数尝试此操作,我会得到一个异常:“语句终止。在语句完成之前,最大递归100已用尽。”@sprinter252:100是CTE最大递归级别的默认值-是。但是,您可以通过指定
SELECT*FROM Waypoints OPTION(MAXRECURSION 2500)
或您喜欢的任何选项(我相信最大值为32767)来增加该值(如果您愿意)。更高的递归级别使用更多的内存,但是。。。。