在下一个最早的日期从另一个表更新1个表

时间:2016-08-31 23:55:41

标签: sql-server

我有2个表:budget和budget_rate:

预算表

资源期小时元 -------- ------ ----- -------
ADMIN03 01/31/16 160 8000
ADMIN03 02/28/16 150 7500

费率表

资源率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  

2 个答案:

答案 0 :(得分:1)

我假设费率表很小,所以我会重新计算它以包含范围列。

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 :(得分: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

创建功能后,您需要删除并重新创建预算表中的Dollars列...

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