2009-10-03 67 views
0

我有3个网站,价格和PriceMonth。网站有很多价格(加入siteId)。 PriceMonth持有Price查询的日期(加入PriceMonth)。SQL更新 - 是否有一个更优雅和有效的方式来做到这一点?

这个想法是,当网站创建为占位符时创建价格记录。

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

我已经编写了一个存储过程的代码。现在请忽略硬编码值。它的工作原理,但它可以变得更简单,更高效?

代码:

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 
+0

你能解释为什么你需要占位符吗?为什么不直接在实际数据中插入价格? – JohnFx 2009-10-03 15:18:49

+0

当然,这是企业的一项要求,所以他们不必一年的所有价格。我要求改变这一点,但我不允许 - 所以简而言之,这并不重要 - 我需要它们。 – Davy 2009-10-03 15:22:30

回答

0

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

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

小心使用这种技术:

  • 如果没有行返回,变量保持不变(空在这种情况下)。
  • 如果返回多行,则分配每行 - 这将最后一组值作为最终值。如果没有指定顺序,那么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 
+0

谢谢 - 这看起来不错。在特定的应用程序中的性能不是问题,但这是一个有用的技术。 – Davy 2009-10-03 15:34:54

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可以使用可能在其中定义的任何索引来至少缩小值的范围。

+0

谢谢Joon - 我收到以下错误: Msg 4104,Level 16,State 1,Line 1 无法绑定多部分标识符“price.priceMonthId”。 消息207,级别16,状态1,行14 无效的列名称'StartDate'。 消息207,级别16,状态1,行15 无效的列名称'StartDate'。 Msg 4104,Level 16,State 1,Line 15 无法绑定多部分标识符“price.SiteId”。 – Davy 2009-10-03 15:28:58

0

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

相关问题