分组依据,分组依据,子查询 - 性能获取前一行值的问题

时间:2009-06-30 04:30:38

标签: ms-access sql-server-2000

我正在使用MS ACCESS 2003

表名 - > tmp_cardevent

PERSONID   CARDEVENTDATE  CARDEVENTTIME

5008       20090805       080000
5008       20090805       140000
5008       20090809       180000
5008       20090809       220000
3405       20090805       080000
3405       20090805       180000
3405       20090809       070000
3405       20090809       230000
3010       20080806       090000
3010       20080806       230000
3010       20080810       100000
3010       20080810       160000

我想显示人员ID的今天时间和前一天时间 前一天意味着不是昨天,特定人员的前一个cardeventtime。

我为获取上一行值

进行了以下查询
select t1.Personid, 
    t1.cardeventdate, 
    t1.cardeventtime, 
    t2.Personid,  
    t2.cardeventdate,
    t2.cardeventtime 
from  tmp_cardevent  t1 inner join tmp_cardevent t2 on t1.cardno = t2.cardno 
where t2.cardeventdate =  (
    select max(cardeventdate)  
    from tmp_cardevent ds 
    where ds.cardeventdate < t1.cardeventdate
        and ds.cardno = t1.cardno 
    ) 

从上面的查询中,上一行显示完美

预期产出

PERSONID   CARDEVENTDATE      LastCARDEVENTDATE  

5008       20090809           20090805       
3405       20090809           20090805       
3010       20080810           20080806     

但是如果在上面的查询中使用group by,order by子查询,则需要花费很多时间才能显示,因为它在大量数据中的性能如此糟糕

那么有人可以帮我找到解决这个问题的最佳方案吗?

或任何其他查询帮助?

2 个答案:

答案 0 :(得分:1)

SELECT
   Seq = identity(int, 1, 1),
   CardNo,
   CardEventDate
INTO #CardSeq
FROM tmp_cardevent
ORDER BY CardNo, CardEventDate

SELECT
   t1.Personid,
   t1.cardeventdate,
   t1.cardeventtime,
   t2.Personid,
   t2.cardeventdate,
   t2.cardeventtime
from
   tmp_cardevent t1
   inner join #CardSeq S1 ON t1.CardNo = S.CardNo
   left join #CardSeq S2 ON t1.CardNo = t2.CardNo and t1.Seq - 1 = t2.Seq
   left join tmp_cardevent t2 on t1.cardno = t2.cardno

DROP TABLE #CardSeq

在CardNo和/或Seq上的临时表上放置索引应该会有所帮助。在填充索引之前使用索引创建临时表可能比使用SELECT INTO后添加索引更好。仅在每列上试验聚簇索引,然后在一列上聚集+在另一列上聚簇,反之亦然,看看哪种方法能够提供最佳性能。

如果您在查询上有条件限制卡号,请在插入临时表中执行此操作,以便它仅适用于必要的内容。

需要左连接,否则第一个事件将永远不会出现。

答案 1 :(得分:0)

您需要在分组列和有序列上建立索引。

e.g。在Customer表中的Last_Name列上创建索引。 创建索引IDX_CUSTOMER_LAST_NAME 在CUSTOMER(Last_Name)

同样,您可以在group by和order子句中使用的列上创建索引。