SQL Update - есть ли более элегантный и эффективный способ сделать это? - PullRequest
0 голосов
/ 03 октября 2009

У меня 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 ]

1 голос
/ 03 октября 2009

Вы можете добавить переменные как объединения к запросу следующим образом:

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 голосов
/ 03 октября 2009

Что касается требования для заполнителей, вы всегда можете использовать левое соединение и COALESCE, чтобы иметь возможность вернуться к цене предыдущего месяца. В качестве альтернативы можно запланировать задачу по созданию цен нового месяца за предыдущий месяц в полночь последнего дня каждого месяца.

0 голосов
/ 03 октября 2009

Вы можете использовать множественное присваивание для установки множества переменных с результатами одного запроса.

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

Остерегайтесь с этой техникой:

  • если строки не возвращаются, переменные остаются неизменными (в данном случае пустым).
  • если возвращаются несколько строк, присваивается каждая строка, которая оставляет последний набор значений в качестве окончательных значений. Если порядок не указан, то сервер sql определяет порядок строк, и любая строка может быть последней.

Вы можете предварительно вычислить диапазон дат, который хотите обновить. Это может позволить использовать индекс по датам.

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...