代码之家  ›  专栏  ›  技术社区  ›  dbStudent

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

  •  0
  • dbStudent  · 技术社区  · 11 年前

    调用表

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

    活动表

    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 回复  |  直到 11 年前
        1
  •  3
  •   Gordon Linoff    11 年前

    在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) .

        2
  •  0
  •   granadaCoder    11 年前

    滞后和超前可能对您有所帮助

    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年内写了一个游标……但没有重新访问过它,看看是否可以重构。 我认为这是一种“命中数个数据库”类型的事情。但这是规则的微小例外……继续追求“基于集合”和非光标的解决方案。

    推荐文章