Незнакомый оператор SQL UPDATE для запуска полного решения - PullRequest
0 голосов
/ 08 июня 2018

Я столкнулся со следующим оператором SQL UPDATE, который вычисляет столбец промежуточного итога в таблице:

UPDATE N1 SET
    RunningTotal = (SELECT SUM (SubTotal)
                    FROM #Sales X1
                    WHERE
                        N1.FiscalYear = X1.FiscalYear AND
                        X1.OrderNumber <= N1.OrderNumber)
FROM
    #Sales N1

Я не встречал этот тип шаблона раньше и из-за трудностей, связанных с поиском SQLЗаявления, я не смог найти объяснения.В частности, я хотел бы знать, как вышеприведенный оператор может обновить всю таблицу;как происходит зацикливание?

Примечание: оператор отлично работает;результаты до и после, как видно из SSMS, выглядят следующим образом:

enter image description here

(я использую SQL Server 2017 Community Edition в Windows 10 x64.)

Ответы [ 3 ]

0 голосов
/ 08 июня 2018

Это на самом деле не зацикливание, но я объясню:

UPDATE N1 SET
    RunningTotal = ...
FROM #Sales N1

Из-за этого обновляется вся таблица.В этом обновлении нет условия where, поэтому каждая строка будет обновлена, несмотря ни на что.Лично я предпочитаю этот стиль псевдонимов таблицы и использование UPDATE для псевдонимов, потому что, когда у вас сложные обновления, это может облегчить просмотр изменений.

Внутренняя часть:

SELECT SUM (SubTotal)
FROM #Sales X1
WHERE N1.FiscalYear = X1.FiscalYear AND
   X1.OrderNumber <= N1.OrderNumber

Получаетсумма продаж за каждый год до и после обработки заказа.Это не зацикливание в коде;он действительно выполняет подзапрос для каждой строки или возвращаемых данных.

0 голосов
/ 08 июня 2018

Лучшим решением вашей проблемы является обновляемый CTE:

WITH toupdate AS 
      (SELECT S.*,
              SUM(SubTotal) OVER (PARTITION BY FiscalYear ORDER BY OrderNumber) AS new_RunningTotal
         FROM #Sales S
      )
UPDATE toupdate
    SET RunningTotal = new_RunningTotal;

. В нем нет ни присоединений, ни соответствующих подзапросов.В общем, оконные функции будут намного быстрее, чем коррелированный эквивалент подзапроса.Обновляемые CTE - это очень хорошая функция SQL Server, которая избавляет вас от дополнительных JOIN.

0 голосов
/ 08 июня 2018

Ваш оператор обновления просто суммирует все строки перед текущим порядковым номером.

Позвольте мне показать вам другой подход:

create table tbl (FiscalYear int, OrderDate date, OrderNumber int, SubTotal decimal(10,2), RunningTotal decimal(10,2));
insert into tbl values
(2011, '20110531', 1, 5000.02, null),
(2011, '20110531', 2, 1000.15, null),
(2011, '20110531', 3,  700.25, null),
(2011, '20110531', 4,  225.02, null),
(2011, '20110531', 5, 1258.25, null),
(2011, '20110531', 6, 1000.00, null),
(2011, '20110531', 7,  695.20, null),
(2011, '20110531', 8,  789.25, null),
(2011, '20110531', 9, 2125.02, null);
GO

Запрос CTE вычисляет совокупные итоги и секундыобновите таблицу.

;with x as 
(
    select FiscalYear,
           OrderDate,
           OrderNumber,
           SubTotal,
           sum(SubTotal) over (partition by FiscalYear 
                               order by FiscalYear, OrderDate, OrderNumber) as CumTotal
    from   tbl
)
update t
set    RunningTotal = CumTotal
from   tbl t
join   x
on     x.Fiscalyear = t.FiscalYear
and    x.OrderDate = t.OrderDate
and    x.OrderNumber = t.OrderNumber;
GO
9 rows affected
select * from tbl;
GO
FiscalYear | OrderDate           | OrderNumber | SubTotal | RunningTotal
---------: | :------------------ | ----------: | :------- | :-----------
      2011 | 31/05/2011 00:00:00 |           1 | 5000.02  | 5000.02     
      2011 | 31/05/2011 00:00:00 |           2 | 1000.15  | 6000.17     
      2011 | 31/05/2011 00:00:00 |           3 | 700.25   | 6700.42     
      2011 | 31/05/2011 00:00:00 |           4 | 225.02   | 6925.44     
      2011 | 31/05/2011 00:00:00 |           5 | 1258.25  | 8183.69     
      2011 | 31/05/2011 00:00:00 |           6 | 1000.00  | 9183.69     
      2011 | 31/05/2011 00:00:00 |           7 | 695.20   | 9878.89     
      2011 | 31/05/2011 00:00:00 |           8 | 789.25   | 10668.14    
      2011 | 31/05/2011 00:00:00 |           9 | 2125.02  | 12793.16    

дБ <> скрипка здесь

...