SQL Update - 有更优雅和有效的方法吗?

时间:2009-10-03 15:13:03

标签: sql sql-server tsql sql-update

我有3个表格Site,Price和PriceMonth。网站有很多价格(在siteId上加入)。 PriceMonth持有一个由Price查询的日期(加入PriceMonth)。

我们的想法是,在将网站创建为占位符时创建价格记录。

当用户点击视图中的价格行时 - 我需要仅更新该年剩余时间的价格,并且仅从该月开始。

我已经为存储过程编写了代码。请暂时忽略硬编码值。它有效但可以更简单,更有效吗?

代码:

DECLARE @startDate smallDateTime                  
DECLARE @roc decimal(5,2)
DECLARE @Lec decimal(5,2)
DECLARE @power decimal(5,2)

SET @roc =  (SELECT roc FROM [Price] WHERE siteId = 77 AND PriceMonthId = 527)
SET @lec = (SELECT lec FROM [Price] WHERE siteId = 77 AND PriceMonthId = 527)   
SET @power = (SELECT [power] FROM [Price] WHERE siteId = 77 AND PriceMonthId = 527) 
SET @startDate = (Select [month] FROM  [PriceMonth] WHERE PriceMonthId = 527) 

UPDATE 
    Price
SET 
    roc = @roc
,   lec = @lec
,   [power] = @power
FROM 
    Price
    INNER JOIN priceMonth pm ON price.priceMonthId = pm.priceMonthId

WHERE
   (DATEPART(mm,pm.[Month]) > DATEPART(mm,@startDate)   AND 
   (DATEPART(yy,pm.[Month]) = DATEPART(yy,@startDate))) AND
    price.SiteId = 77 

3 个答案:

答案 0 :(得分:1)

您可以将变量作为联接添加到查询中,如下所示:

UPDATE     p
SET         roc = sourcePrice.roc,   
            lec = sourcePrice.lec,   
            [power] = sourcePrice.[power]
FROM        Price p
            INNER JOIN [Price] sourcePrice
            on p.siteId = sourcePrice.siteId
            and sourcePrice.siteId = 527
            INNER JOIN priceMonth pm 
            ON price.priceMonthId = pm.priceMonthId
            INNER JOIN priceMonth sourcepm
            ON sourcepm.PriceMonthId = 527

WHERE   pm.[Month] > sourcepm.StartDate
AND     (DATEPART(yy,pm.[Month]) = DATEPART(yy,sourcepm.StartDate))) 
AND     price.SiteId = 77

另请注意,我已从您的某个日期比较中删除了该函数 - 这样SQL Server可以使用可能在其上定义的任何索引来至少缩小值的范围。

答案 1 :(得分:0)

您可以使用多个赋值来设置多个变量和一个查询的结果。

SELECT top 1
  @roc = roc,
  @lec = lec,
  @power = power
FROM Price
WHERE siteId = 77 and pricemonthid = 527

注意这种技巧:

  • 如果没有返回任何行,则变量保持不变(在这种情况下为null)。
  • 如果返回多行,则分配每一行 - 这将最后一组值保留为最终值。如果没有指定排序,则sql server确定行的顺序,任何行都可以是最后一行。

您可以预先计算要更新的日期范围。这可能允许日期索引有用。

DECLARE @StartRange datetime, @EndRange datetime

SET @StartRange = DateAdd(mm, DateDiff(mm, @startDate, 0), 0)
SET @EndRange = DateAdd(yy, 1 + DateDiff(yy, @StartRange, 0), 0)

UPDATE...
WHERE @StartRange <= pm.Month AND pm.Month < @EndRange
  AND price.SiteId = 77

答案 2 :(得分:0)

关于占位符的要求,您始终可以使用LEFT JOIN和COALESCE来回退到上个月的价格。或者,安排任务以创建每个月最后一天午夜的上个月的新月价格。