2015-06-02 3 views
1

У меня есть два sql tablespricetbl и paymenttbl. Из-за того, что цены на каждый день меняются, мне нужно обновить paymenttbl с ценами в нужное время. Если сделка совершена после date-effective цены продукта, то цена сделки в paymenttbl такая же, как цена последнего продукта (если эффективная дата меньше даты транзакции). Я не только хочу ограничиться здесь, я хочу перебирать всю таблицу, чтобы внести изменения в данные, чтобы каждая транзакция имела правильную цену.Оптимизация процедуры VBA, которая выполняет итерации по двум различным таблицам данных

PriceTbl 


pID| Price| Date Effective 
--------------------------- 
1 | 10 | 01-12-2014 
2 | 20 | 01-02-2015 
3 | 20 | 02-12-2014 
2 | 40 | 20-03-2015 
1 | 50 | 02-03-2015 
4 | 34 | 20-02-2015 
1 | 40 | 25-05-2015 

PaymentTbl 

payID | pID | transDate | Price 
-------------------------------- 
    1 | 1 | 02-12-2014| 05 
    2 | 1 | 04-03-2015| 10 
    3 | 2 | 21-04-2015| 35 
    4 | 3 | 03-12-2014| 15 

Ожидаемая таблицу paymenttbl после выполнения запроса

payID | pID | transDate | Price 
-------------------------------- 
    1 | 1 | 02-12-2014| 10 
    2 | 1 | 04-03-2015| 50 
    3 | 2 | 21-04-2015| 40 
    4 | 3 | 03-12-2014| 20 

Что будет самым быстрым и простым способом для извлечения и обновления данных? Мой текущий способ занимает около 30 минут, чтобы обновить таблицу, так как я перебираю через paytbl, затем перебираю по pricetbl и сравниваю его с каждым элементом в paytbl.

Мой код:

Function updateWorktoDateEff() 
    Dim rt As DAO.Recordset 
    Dim wt As DAO.Recordset 
    Dim db As DAO.Database 
    Dim sqlrt As String 
    Dim sqlwt As String 

    Set db = CurrentDb 

    sqlrt = "select * from pricetbl where (dailyrate IS NOT NULL) and (dateeffective is not null) order by id, dailyrate" 
    sqlwt = "select * from paymenttbl where (id > 0) order by id, date" 

    Set rt = db.OpenRecordset(sqlrt) 
    Set wt = db.OpenRecordset(sqlwt) 

    Do While Not wt.EOF 

     Do While Not ratetable.EOF 
      If rt!ID = wt!ID Then 
       If rt <= wt!Date Then 

         wt.Edit 
         wt!Rate = ratetable!dailyrate 
         wt.Update 
        End If 
      ElseIf ratetable!ID > worktable!ID Then 
       Exit Do 
      End If 
      rt.MoveNext 
     Loop 
     rt.MoveFirst 
     wt.MoveNext 'move to the next worktbl record 
    Loop 
End Function 

просто итерация/получение данных не будет делать это. Мне также нужно будет изменить его.

ответ

0

Наиболее эффективным способом выполнения этого обновления является не использование наборов записей и переход строки за строкой, а использование SQL для обновления на основе набора. Я попробовал написать один запрос на обновление, но MS-Access потрудился в том, что запрос не был обновляемым, поэтому я вместо этого написал два запроса: один для записи во временную таблицу (tempNewPrices) и один для обновления PaymentTbl с использованием этой временной таблицы ,

Вот первый запрос, чтобы создать временную таблицу, которая включает в себя новый столбец NewPrice:

SELECT PaymentTbl.payID, PaymentTbl.pID, PaymentTbl.transDate, PaymentTbl.Price, 
(
    SELECT [Price] 
    FROM PriceTbl pr 
    WHERE pr.pID = PaymentTbl.pID 
    AND pr.[Date Effective] = (
    SELECT Max([Date Effective]) 
    FROM PriceTbl pr2 
    WHERE pr2.pID = pr.pID 
    AND pr2.[Date Effective]< PaymentTbl.[transDate] 
) 
) AS NewPrice INTO tempNewPrices 
FROM PaymentTbl; 

и вот запрос на обновление, чтобы изменить значение цены в PaymentTbl:

UPDATE tempNewPrices 
INNER JOIN PaymentTbl ON tempNewPrices.payID = PaymentTbl.payID 
SET PaymentTbl.Price = [NewPrice]; 

Это должно быть гораздо более эффективный, чем цикл с помощью наборов записей.