SQL Server中的游标:高性能惩罚

时间:2015-07-31 13:33:22

标签: sql sql-server join cursors

CallTable

CallId |    Date | Time |   MemberID |  CallDuration
12     |    02.02.2015| 13:33:54|   3245|   234 |
13     |    02.02.2015| 13:37:24|   3245|   33  |

ActivityTable

Date*********** Time*** MemberId    ***Activity
02.02.2015***   13:31:22*** 3245*** A
02.02.2015***   13:34:54*** 3245*** B

我的老板想知道接到电话时活动成员(员工)正在做什么(或之前的活动)。该数据存储在上面给出的两个表中。

我正在使用Cursor从CallTable获取每一行,然后使用循环中的另一个游标来检索最后一个活动。 CallTable中有大约100万行,处理这个行需要很长时间。 CallTable中没有基于CallID的主 - 外键关系。

这里的任何人都可以建议我如何通过JOIN实现这一点并避免使用游标?

提前致谢

2 个答案:

答案 0 :(得分:3)

在SQL Server中,您可以使用相关子查询或使用APPLY来执行此操作。例如:

select c.*, a.activity
from calltable c outer apply
     (select top 1 a.*
      from activitytable a
      where a.memberId = c.memberId and
            a.datetime <= c.datetime
      order by a.datetime asc
     ) a;

这假设日期/时间在同一列中,这是存储此值的正确方法。如果它们位于不同的列中,则类似(但更复杂)的逻辑可以工作。

为了提高性能,您需要activitytable(memberid, datetime)上的索引。

答案 1 :(得分:0)

滞后和潜在客户可能对您有所帮助

http://blog.sqlauthority.com/2013/09/22/sql-server-how-to-access-the-previous-row-and-next-row-value-in-select-statement/

这是一个Northwind迷你示例。

select * , DaysSincePreviousOrder = datediff(d , PreviousValue, OrderDate)  from (

  SELECT
LAG(p.OrderDate) OVER (ORDER BY p.CustomerID, p.OrderDate) PreviousValue,
p.CustomerID, p.OrderDate,
LEAD(p.OrderDate) OVER (ORDER BY p.CustomerID , p.OrderDate) NextValue
FROM dbo.Orders p where CustomerID = 'anatr' ) as derived1
where derived1.OrderDate = (select max(OrderDate) from dbo.Orders o where o.CustomerID = derived1.CustomerID)

GO

99.9%的事情可以在没有光标的情况下完成。我在10年内写了一个光标......并且没有重新审视它,看看我是否可以重构。 我认为这是一个&#34;打了几个数据库&#34;事物的类型。但这是规则的微不足道的例外......继续追求&#34;基于集合&#34;和非光标解决方案。