У меня есть некоторые данные, пример реального мира. Чтобы отображать данные определенным образом, данные хранятся таким образом, что я должен манипулировать им, чтобы получить нужные результаты. По сути, существуют два разных типа счетов-фактур: предварительный счет-фактура (P), когда суммы выставлены счету перед обработкой заказа; и стандартный счет-фактура (I), где остаток выставляется после доставки. В обычных обстоятельствах вы ожидали, что стандартный счет-фактура будет иметь вычитаемую из него сумму перед выставлением счета, например, если предварительный счет был за 2 доллара, а заказ был равен 10 долларам США, что стандартный счет-фактура будет составлять 8 долларов США. Вместо этого стандартный счет-фактура хранится как 10 долларов США.Есть ли способ использования оконных функций для упрощения этого запроса?
Ниже приведен полный рабочий запрос (этот запрос работает! Это ловушка!), Который заполняет данные и возвращает результаты, которые я хочу. Цель состоит в том, чтобы принять сумму счета и, если это предварительный счет, вернуть эту сумму; но если это стандартный счет-фактура, «использовать» значение предварительного счета и вернуть новую сумму, минимальный ноль. Я включил шесть сценариев, поскольку предварительный счет-фактура может быть любой суммой и может быть технически обязательным в любое время.
Любая помощь по этому вопросу будет высоко оценена. Я попробовал некоторые функции окон, в том числе UNBOUNDED PRECEDING, но мне всегда казалось, что мне нужно быть рекурсивным и переходить в бесконечный цикл. Отсюда мой подход грубой силы, ниже.
DECLARE @PData TABLE (
CustNum INT
,TransNum INT
,InvType NVARCHAR(1)
,InvAmt DECIMAL(5,2)
,CRank INT
,TRank INT
,ModInvAmt DECIMAL(5,2)
)
INSERT INTO @PData (
CustNum
,TransNum
,InvType
,InvAmt
)
VALUES
(124, 1,'P',2)
,(124, 2,'I',10)
,(124, 3,'I',10)
,(153, 4,'I',10)
,(153, 5,'P',2)
,(153, 6,'I',10)
,(324, 7,'I',10)
,(324, 8,'I',10)
,(324, 9,'P',2)
,(441,10,'P',12)
,(441,11,'I',10)
,(441,12,'I',10)
,(455,13,'I',10)
,(455,14,'P',12)
,(455,15,'I',10)
,(667,16,'I',10)
,(667,17,'I',10)
,(667,18,'P',12)
UPDATE pd1
SET CRank = pd2.CDR
FROM @PData pd1
JOIN (SELECT CustNum, TransNum, DENSE_RANK() OVER (ORDER BY CustNum) AS CDR
FROM @PData) pd2
ON pd1.TransNum = pd2.TransNum
UPDATE pd1
SET TRank = pd2.TDR
FROM @PData pd1
JOIN (SELECT CustNum, TransNum, DENSE_RANK() OVER (PARTITION BY CustNum ORDER BY TransNum) AS TDR
FROM @PData) pd2
ON pd1.TransNum = pd2.TransNum
DECLARE @Counter1 INT
,@Counter2 INT
,@CBal DECIMAL(5,2)
,@TNum INT
,@IAmt DECIMAL(5,2)
SET @Counter1 = 0
WHILE @Counter1 < (SELECT MAX(CRank) FROM @PData)
BEGIN
SET @Counter1 += 1
SET @CBal = 0
SET @Counter2 = 0
WHILE @Counter2 < (SELECT MAX(TRank) FROM @PData WHERE CRank = @Counter1)
BEGIN
SET @Counter2 += 1
SET @TNum = (SELECT TransNum FROM @PData WHERE CRank = @Counter1 AND TRank = @Counter2)
SET @IAmt = (SELECT InvAmt FROM @PData WHERE TransNum = @TNum)
IF (SELECT InvType FROM @PData WHERE TransNum = @TNum) = 'P'
BEGIN
UPDATE @PData SET ModInvAmt = @IAmt WHERE TransNum = @TNum
SET @CBal += [email protected]
END
ELSE
BEGIN
UPDATE @PData SET ModInvAmt = (ABS(@[email protected])+(@[email protected]))/2 -- MINIMUM = 0
WHERE TransNum = @TNum
SET @CBal += (@IAmt - (ABS(@[email protected])+(@[email protected]))/2)
END
END
END
SELECT CustNum
,TransNum
,InvType
,InvAmt
,ModInvAmt
FROM @PData
Вот результаты, которые я получаю:
Я обычно не сообщают о первоначальной суммы счета - только новый - но я включил его здесь, так что это более ясно, как это изменило.
CustNum TransNum InvType InvAmt ModInvAmt
124 1 P 2.00 2.00
124 2 I 10.00 8.00
124 3 I 10.00 10.00
153 4 I 10.00 10.00
153 5 P 2.00 2.00
153 6 I 10.00 8.00
324 7 I 10.00 10.00
324 8 I 10.00 10.00
324 9 P 2.00 2.00
441 10 P 12.00 12.00
441 11 I 10.00 0.00
441 12 I 10.00 8.00
455 13 I 10.00 10.00
455 14 P 12.00 12.00
455 15 I 10.00 0.00
667 16 I 10.00 10.00
667 17 I 10.00 10.00
667 18 P 12.00 12.00
Мой образ в конце не отображается? – DaveX
Полезно пометить вопросы базы данных как с помощью соответствующего программного обеспечения (MySQL, Oracle, DB2, ...) и версии, например. 'SQL-сервер-2014'. Различия в синтаксисе и особенностях часто влияют на ответы. – HABO
Сделано, спасибо за идею. – DaveX