Группировать по, упорядочивать по, подзапросам - проблема с производительностью для получения значения предыдущей строки - PullRequest
0 голосов
/ 30 июня 2009

Я использую 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

Я хочу отобразить текущее и предыдущее время для идентификатора человека. Предыдущий день означает не вчерашний день, а предыдущее время cardevent для конкретного человека.

Я делаю следующий запрос для получения значения предыдущей строки

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     

Но если в приведенном выше запросе используются групповые, упорядоченные подзапросы, это не займет много времени, так как производительность при большом количестве данных очень плоха

Так может ли кто-нибудь помочь мне найти лучшее решение для такой проблемы?

или любой другой запрос справки?

Ответы [ 2 ]

1 голос
/ 01 июля 2009
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. Поэкспериментируйте с кластеризованным индексом только в каждом столбце, затем кластеризуйте в одном столбце + некластеризованном в другом и наоборот, чтобы увидеть, что дает наилучшую производительность.

Если в запросе есть условия для ограничения номеров карт, сделайте это на вставке во временную таблицу, чтобы она работала только на том, что необходимо.

Нужны левые соединения, иначе первое событие никогда не появится.

0 голосов
/ 30 июня 2009

У вас должны быть индексы для ваших сгруппированных и упорядоченных столбцов.

например. создания индекса по столбцу Last_Name в таблице Customer. CREATE INDEX IDX_CUSTOMER_LAST_NAME на ЗАКАЗЧИКА (Фамилия)

Аналогичным образом вы можете создавать индексы для столбцов, используемых в вашей группе, с помощью предложений и заказов.

...