2016-08-31 2 views
1

У меня есть 2 таблицы: бюджет и budget_rate:обновления 1 таблица из другой таблицы по следующему ранней дате

Бюджет Таблицы период

ресурса часов долларов
-------- ---- - ----- -------
ADMIN03 01/31/16 160 8000
ADMIN03 02/28/16 150 7500

Оценить Таблица

resou Скорость RCE eff_date
-------- ---- --------
ADMIN03 50,00 01/01/16
ADMIN03 52,50 01/01/17

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

Можно ли это сделать с помощью одного UPDATE?

Что-то вроде:

update b 
    set b.dollars = b.hours*r.rate 
from 
    budget b join rate r on 
    b.resource = r.resource and 
    b.period >= r.eff_date 

ответ

1

Я предполагаю, что таблица ставка realtive мала, так что я бы пересчитывать его, чтобы иметь столбцы диапазона.

with oRates as (
     select resource, 
       rate, 
       eff_date, 
       ROW_NUMBER() over(partition by resource order by eff_date desc) rn 
     from Rates 
    ), 
    pRates as (
     select r1.resource, 
       r1.rate, 
       r1.eff_date from_date, 
       isnull(r2.eff_date,'2070-01-01') to_date 
     from oRates r1 
      left join oRates r2 on (r1.rn = r2.rn+1) 
    ) 
update b 
set dollars = hours * r.rate 
from Budget b 
    join pRates r on (b.resource = r.resource 
        and b.period >= from_date 
        and b.period < to_date) 
+1

Спасибо! Это сработало отлично. – user2378895

0

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

Пример того, как это можно сделать, можно увидеть здесь: formula for computed column based on different table's column

Для рабочего примера с вашими данными, вы бы создать такую ​​функцию:

CREATE FUNCTION dbo.ufn_BudgetDollars (@resource NVARCHAR(255), @date DATE, @hours INT) 
RETURNS DECIMAL(10, 2) 
AS BEGIN 
    DECLARE @out DECIMAL(10, 2); 
    SELECT @out = @hours * rate 
    FROM (
     SELECT rate, ROW_NUMBER() OVER (ORDER BY eff_date DESC) rn 
     FROM tblRate 
     WHERE eff_date <= @date 
     AND resource = @resource) T 
    WHERE RN = 1; 
    RETURN @out; 
END 
GO 

Когда вы создала вашу функцию, вы хотели бы сбросить и воссоздать колонку «Доллары» в таблице бюджета ...

ALTER TABLE tblBudget DROP COLUMN Dollars; 
ALTER TABLE tblBudget ADD Dollars AS dbo.ufn_BudgetDollars(resource, Period, Hours); 
GO