Как я вычисляю рабочее общее количество в SQL, не используя курсор?

Строки:

>>> n = '4'
>>> print(n.zfill(3))
004

И для чисел:

>>> n = 4
>>> print('%03d' % n)
004
>>> print(format(n, '03')) # python >= 2.6
004
>>> print('{0:03d}'.format(n))  # python >= 2.6
004
>>> print('{foo:03d}'.format(foo=n))  # python >= 2.6
004
>>> print('{:03d}'.format(n))  # python >= 2.7 + python3
004
>>> print('{0:03d}'.format(n))  # python 3
004
>>> print(f'{n:03}') # python >= 3.6
004

Строковая документация форматирования .

24
задан ErikE 11 April 2014 в 04:49
поделиться

8 ответов

Возможно, вы захотите взглянуть на обновление решения для локальных переменных здесь: http://geekswithblogs.net/Rhames/archive/2008/10/28/calculating-running -totals-in-sql-server-2005 --- the-optimal.aspx

DECLARE @SalesTbl TABLE (DayCount smallint, Sales money, RunningTotal money)

DECLARE @RunningTotal money

SET @RunningTotal = 0

INSERT INTO @SalesTbl 
SELECT DayCount, Sales, null
FROM Sales
ORDER BY DayCount

UPDATE @SalesTbl
SET @RunningTotal = RunningTotal = @RunningTotal + Sales
FROM @SalesTbl

SELECT * FROM @SalesTbl

Превосходит все другие методы, но есть некоторые сомнения относительно гарантированного порядка строк. Хотя, похоже, работает нормально, когда временная таблица проиндексирована ..

  • Вложенный подзапрос 9300 мс
  • Самостоятельное соединение 6100 мс
  • Курсор 400 мс
  • Обновление локальной переменной 140 мс
20
ответ дан 28 November 2019 в 23:13
поделиться

В Oracle и PostgreSQL 8.4 вы можете использовать оконные функции:

SELECT  SUM(value) OVER (ORDER BY id)
FROM    mytable

В MySQL , вы можете использовать переменную сеанса для той же цели:

SELECT  @sum := @sum + value
FROM    (
        SELECT  @sum := 0
        ) vars, mytable
ORDER BY
        id

В SQL Server это редкий пример задачи, для которой курсор является предпочтительным решением.

8
ответ дан 28 November 2019 в 23:13
поделиться

SQL может создавать промежуточные итоги без использования курсоров, но это один из немногих случаев, когда курсор на самом деле более эффективен, чем решение на основе наборов (с учетом операторов в настоящее время доступно в SQL Server). В качестве альтернативы, функция CLR иногда может хорошо проявить себя. Ицик Бен-Ган написал отличную серию статей в журнале SQL Server Magazine по запуску агрегатов. Серия завершилась в прошлом месяце, но вы можете получить доступ ко всем статьям, если у вас есть онлайн-подписка.

Изменить: вот его последняя статья из серии (SQL CLR). Учитывая, что вы можете получить доступ ко всей серии, купив онлайн-абонемент на месяц на один месяц - менее 6 долларов - это того стоит, если вам интересно взглянуть на проблему со всех сторон. Ицик - Microsoft MVP и очень кодировщик TSQL.

10
ответ дан 28 November 2019 в 23:13
поделиться

Пример вычисления промежуточной суммы для каждой записи, но только если OrderDate для записей относится к той же дате. Как только OrderDate относится к другому дню, будет начата новая промежуточная сумма, которая будет накапливаться для нового дня: (предположим структуру и данные таблицы)

select O.OrderId,
convert(char(10),O.OrderDate,101) as 'Order Date',
O.OrderAmt, 
(select sum(OrderAmt) from Orders 
                      where OrderID <= O.OrderID and 
                           convert(char(10),OrderDate,101)
                         = convert(char(10),O.OrderDate,101))
                               'Running Total' 
from Orders O
order by OrderID

Вот результаты, возвращенные из запроса с использованием образца таблицы заказов:

OrderId     Order Date OrderAmt   Running Total                            
----------- ---------- ---------- ---------------
1           10/11/2003 10.50      10.50
2           10/11/2003 11.50      22.00
3           10/11/2003 1.25       23.25
4           10/12/2003 100.57     100.57
5           10/12/2003 19.99      120.56
6           10/13/2003 47.14      47.14
7           10/13/2003 10.08      57.22
8           10/13/2003 7.50       64.72
9           10/13/2003 9.50       74.22

Обратите внимание, что «Промежуточная сумма» начинается со значения 10,50, затем становится 22,00 и, наконец, становится 23.25 для OrderID 3, поскольку все эти записи имеют один и тот же OrderDate (10.11.2003). Но когда отображается OrderID 4, текущая сумма сбрасывается, а текущая сумма начинается заново. Это связано с тем, что OrderID 4 имеет другую дату для его OrderDate, а затем OrderID 1, 2 и 3. Расчет этой промежуточной суммы для каждой уникальной даты снова выполняется с помощью коррелированного подзапроса, хотя требуется дополнительное условие WHERE, которое определили, что OrderDate в разных записях должен быть в один и тот же день.

4
ответ дан 28 November 2019 в 23:13
поделиться

В SQLTeam есть также статья о вычислении промежуточных итогов. Существует сравнение трех способов сделать это, а также некоторые измерения производительности:

  • с использованием курсоров
  • с использованием подзапроса (согласно сообщению SQLMenace)
  • с использованием CROSS JOIN

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

1
ответ дан 28 November 2019 в 23:13
поделиться

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

create table #Test  (id int, Value decimal(16,4))
insert #Test values(1,100)
insert #Test values(2,100)
insert #Test values(3,100)
insert #Test values(4,200)
insert #Test values(5,200)
insert #Test values(6,200)
insert #Test values(7,200)

select *,(select sum(Value) from  #Test t2 where t2.id <=t1.id) as SumValues
 from #test t1

id  Value       SumValues
1   100.0000    100.0000
2   100.0000    200.0000
3   100.0000    300.0000
4   200.0000    500.0000
5   200.0000    700.0000
6   200.0000    900.0000
7   200.0000    1100.0000
1
ответ дан 28 November 2019 в 23:13
поделиться

Вы можете просто включить коррелированный подзапрос в предложение select. (Это будет плохо работать для очень больших наборов результатов), но

   Select <other stuff>,
       (Select Sum(ColumnVal) From Table
        Where OrderColumn <= T.OrderColumn) As RunningTotal
   From Table T
   Order By OrderColumn
2
ответ дан 28 November 2019 в 23:13
поделиться

Этот бит SELECT @nvcConcatonated возвращает только единственное объединенное значение. (Хотя он вычисляет промежуточные значения для каждой строки, вы можете получить только окончательное значение.)

Итак, я думаю, что ответ отрицательный. Если вам нужно одно итоговое значение суммы, вы, конечно, просто используете SUM .

Я не говорю, что вы не можете этого сделать, я просто говорю, что вы не можете сделать это с помощью этого «трюк».

0
ответ дан 28 November 2019 в 23:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: