Гость
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / вычитывание по очереди до нуля - остаток / 3 сообщений из 3, страница 1 из 1
12.06.2020, 14:59
    #39968592
zindur
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вычитывание по очереди до нуля - остаток
попалась мне тут задачка, думал с курсором, но думаю есть и другие варианты :)
* совершается иногда покупка на определенную сумму (каждый раз когда покупается создается ячейка/склад) = "Purchase"
* совершается со временем продажа = "Sale"

- условие, при транзакции Sale, сумма вчитывается сначала с первой покупки пока в той ячейки/склад есть остаток
если мало осталось то снимаем до нуля и переходим на следующую ячейку/склад.

- надо узнать остаток на время транзакции в каждой ячейки

Код: 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.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
drop table if exists #WorkingTable

SELECT IDENTITY(int, 1, 1) as RowNumber , TradeType,	cAST(TradeDate as DateTime) as TradeDate
, CAST(Amount AS float) as Amount
, case when TradeType = 'Purchase' THEN 
	Row_NUmber () over (partition by TradeType order by TradeDate ) 
	ELSE NULL
	END PoolId
into #WorkingTable
FROM (
VALUES 
('Purchase',	'1/31/2020',13234589.20)
,('Sale',	'1/31/2020',	1000000.00)
,('Sale',	'1/31/2020',	1000000.00)
,('Sale',	'1/31/2020',	1000000.00)
,('Sale',	'1/31/2020',	1234589.20)
,('Sale',	'1/31/2020',	1000000.00)
,('Sale',	'1/31/2020',	1500000.00)
,('Sale',	'1/31/2020',	1000000.00)
,('Purchase',	'2/28/2020',	2000000.00)
,('Sale',	'2/28/2020',	1000000.00)
,('Sale',	'2/28/2020',	1000000.00)
,('Sale',	'3/6/2020',		2750000.00)
,('Purchase',	'3/11/2020',	2000000.00)
,('Purchase',	'3/12/2020',	2000000.00)
,('Sale',	'3/12/2020',	2000000.00)
,('Purchase',	'3/17/2020',	3000000.00)
,('Sale',	'3/17/2020',	1000000.00)

) AS vtable 
( TradeType,	TradeDate,	Amount)

;WITH cte as (
select *
,  CASE WHEN TradeType ='Purchase' THEN 
		cast(RowNumber as varchar) + '_Purchase'
		ELSE NULL
	END	as Pivot_Purchase_left
, CASE WHEN TradeType ='Sale' THEN 
		Amount * -1
		ELSE NULL
	END	as Sale
from #WorkingTable
)
select *
from 
(
  select *
  from cte
) src
pivot
(
  sum(Amount)
  for Pivot_Purchase_left in ([1_Purchase], [2_Purchase], [3_Purchase], [4_Purchase], [5_Purchase])
) piv
order by TradeDate




спасибо :)

PS: сервер 2016
...
Рейтинг: 0 / 0
12.06.2020, 20:43
    #39968694
PizzaPizza
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вычитывание по очереди до нуля - остаток
zindur,

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

Код: 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.
with a as(
SELECT *
FROM (
VALUES 
(1,'Purchase',	'1/31/2020',13234589.20)
,(2,'Sale',	'1/31/2020',	1000000.00)
,(3, 'Sale',	'1/31/2020',	1000000.00)
,(4, 'Sale',	'1/31/2020',	1000000.00)
,(5, 'Sale',	'1/31/2020',	1234589.20)
,(6, 'Sale',	'1/31/2020',	1000000.00)
,(7, 'Sale',	'1/31/2020',	1500000.00)
,(8, 'Sale',	'1/31/2020',	1000000.00)
,(9, 'Purchase',	'2/28/2020',	2000000.00)
,(10, 'Sale',	'2/28/2020',	1000000.00)
,(11, 'Sale',	'2/28/2020',	1000000.00)
,(12, 'Sale',	'3/6/2020',		2750000.00)
,(13, 'Purchase',	'3/11/2020',	2000000.00)
,(14, 'Purchase',	'3/12/2020',	2000000.00)
,(15, 'Sale',	'3/12/2020',	2000000.00)
,(16, 'Purchase',	'3/17/2020',	3000000.00)
,(17, 'Sale',	'3/17/2020',	1000000.00)

) AS vtable 
( id, TradeType,	TradeDate,	Amount)),
b as 
(
    select id, TradeType, TradeDate, 
    case WHEN TradeType='Sale' THEN Amount*(-1) ELSE Amount END as Amount
    from a
)

select *, sum(amount) over (order by id) from b



кстати для денег float лучше не использовать, decimal для этого есть

и TradeDate не содержит достаточной точности для сортировки, так как у вас важен порядок операций и в одну дату может быть несколько операций, которые не поделятся по дате.
...
Рейтинг: 0 / 0
17.06.2020, 16:17
    #39970264
zindur
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вычитывание по очереди до нуля - остаток
примерно так должно получится...
Вычитывать - с первой не нулевой транзакции (Purchase) (пока есть остаток) - Sale
Если Purchase - дошел до нуля - переходим на следующий Purchase
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / вычитывание по очереди до нуля - остаток / 3 сообщений из 3, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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