2009-10-03 36 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以便能夠回退到前一個月的價格。或者,安排任務以在每個月的最後一天的午夜前一個月創建新的月份價格。

相關問題