powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Запрос с нарастающим итогом
7 сообщений из 7, страница 1 из 1
Запрос с нарастающим итогом
    #39827926
Alexey30
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день.
Что-то торможу с совсем простым, по идее, запросом.
Если упростить, то есть такая таблица (приходы/возвраты):

DECLARE @a table (id int, quan int)

INSERT @a VALUES (1, 200), (2, 100), (3,-150), (4,200), (5,-70)

Заранее известно, что отрицательных значений не может быть больше положительных (то есть возвратов не может быть больше приходов).
То есть в первой партии пришло 200, во второй 100, затем было возвращено 150, затем пришло 200 и опять возврат 70.
Возврат осуществляется в обратном порядке, то есть начиная с последней партии.
Необходимо получить остатки в таком виде:
1 150
4 130

То есть от первой партии осталось 150, так как от второй партии не осталось ничего (100-150) и от четвертой партии осталось 130, так как пришло 200 и возврат 70.

Каким запросом это вычислить наиболее "красиво"?

Спасибо.
...
Рейтинг: 0 / 0
Запрос с нарастающим итогом
    #39827979
_human
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexey30,

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
DECLARE @a table (id int, quan int)

INSERT @a VALUES (1, 200), (2, 100), (3,-150), (4,200), (5,-70)

;with grp_cte as 
(select id, quan
	,row_number() over(order by id)-row_number() over(partition by sign(quan) order by id) as grp
from @a)

, in_cte as (
select *, DENSE_RANK() over(order by grp) as g
from grp_cte
where quan>0 )

,out_cte as
(
select *, DENSE_RANK() over(order by grp) as g
from grp_cte
where quan<0 )

, union_cte as (
select * from in_cte
union all
select * from out_cte )

select min(id), sum(quan)
from union_cte
group by g



Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
DECLARE @a table (id int, quan int)

INSERT @a VALUES (1, 200), (2, 100), (3,-150), (4,200), (5,-70)

;with anal_cte as (
select id, quan
	, sum(
	  case sign(quan)
		when 1 then 0
		when -1 then 1
	  end) over(order by id desc) as g
from @a)

select min(id), sum(quan)
from anal_cte
group by g
...
Рейтинг: 0 / 0
Запрос с нарастающим итогом
    #39828061
Alexey30
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
_human,

Спасибо большое, второй вариант отличный!
...
Рейтинг: 0 / 0
Запрос с нарастающим итогом
    #39828063
Alexey30
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
_human,

Ан-нет...
Неверно работает при двух отрицательных подряд...

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
DECLARE @a table (id int, quan int)

INSERT @a VALUES (1, 200), (2, 100), (3,-150), (4,200), (5,-70), (6,-30)

;with anal_cte as (
select id, quan
	, sum(
	  case sign(quan)
		when 1 then 0
		when -1 then 1
	  end) over(order by id desc) as g
from @a)

select min(id), sum(quan)
from anal_cte
group by g
...
Рейтинг: 0 / 0
Запрос с нарастающим итогом
    #39828072
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пишите явно номер партии возврата и минуют вас геморрой и печали.

Или объединяйте идущие подряд возвраты в один возврат.
...
Рейтинг: 0 / 0
Запрос с нарастающим итогом
    #39828136
Cristiano_Rivaldo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Alexey30,

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
;WITH cte (id,quant_src,quant_over)
AS 
(
	SELECT	TOP 1
			a.id,
			a.quan		AS quant_src,
			a.quan		AS quant_over
	FROM @a AS a
	ORDER BY a.id DESC 
	
	UNION ALL
	
	SELECT	a.id,
			a.quan,
			CASE WHEN C.quant_src > 0 AND A.quan < 0  -- был "переход"
					THEN A.quan
				ELSE c.quant_over + a.quan
			END 
	FROM cte AS c
		-- из-за органичений в cte на top  и агрегацию
		CROSS APPLY
		(
			SELECT 
					A.id,
					A.quan,
					ROW_NUMBER() OVER (ORDER BY a.id DESC ) n  
			FROM @a AS a
			WHERE a.id < c.id
		) A
	WHERE A.n = 1
)
SELECT *
FROM cte AS c
WHERE c.quant_over > 0
ORDER BY c.id
...
Рейтинг: 0 / 0
Запрос с нарастающим итогом
    #39828731
Alexey30
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Cristiano_Rivaldo,

Спасибо большое!
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Запрос с нарастающим итогом
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]