我正在尝试实施借记 - 贷方解决系统,但我很难根据集合来表达逻辑。
假设我有一个Orders表:
Id OrderId Amount AdjustmentFlag
1 1 10.00 0
2 1 10.00 1
3 1 10.00 2
4 2 20.00 1
5 2 20.00 2
6 2 20.00 2
7 3 30.00 1
8 4 40.00 0
9 4 40.00 0
10 4 40.00 1
11 5 50.00 0
12 5 50.00 1
13 5 60.00 2
14 5 60.00 1
15 5 60.00 2
16 5 70.00 1
我需要根据他们是否有匹配的“已取消”标记来挑选仍然有效的Id
。
0 - Original Order
1 - Cancelled Order
2 - Adjusted Order
1
与0
或2
匹配,优先于0
。1
标志不匹配,则会被忽略。鉴于以上例子:
可能的结果是[1,2,4,5,7,8,10,11,12,13,14,16](较低的Id有偏好)或[1,2,4,6,7 ,9,10,11,12,14,15,16](更高的Id有偏好)。只要结果是确定性的,任何一个都可以工作。
创建脚本:
CREATE TABLE [Order]
(
Id INT IDENTITY NOT NULL PRIMARY KEY
,OrderId INT NOT NULL
,Amount MONEY NOT NULL
,AdjustmentFlag TINYINT NOT NULL
);
INSERT INTO [Order](OrderId, Amount, AdjustmentFlag)
SELECT 1, 10.00, 0
UNION ALL
SELECT 1, 10.00, 1
UNION ALL
SELECT 1, 10.00, 2
UNION ALL
SELECT 2, 20.00, 1
UNION ALL
SELECT 2, 20.00, 2
UNION ALL
SELECT 2, 20.00, 2
UNION ALL
SELECT 3, 30.00, 1
UNION ALL
SELECT 4, 40.00, 0
UNION ALL
SELECT 4, 40.00, 0
UNION ALL
SELECT 4, 40.00, 1
UNION ALL
SELECT 5, 50.00, 0
UNION ALL
SELECT 5, 50.00, 1
UNION ALL
SELECT 5, 60.00, 2
UNION ALL
SELECT 5, 60.00, 1
UNION ALL
SELECT 5, 60.00, 2
UNION ALL
SELECT 5, 70.00, 1
这是我目前的部分解决方案:
WITH Orders AS
(
SELECT
Id,
OrderId,
Amount,
AdjustmentFlag,
EffectiveOrder = ROW_NUMBER() OVER (PARTITION BY OrderId, Amount ORDER BY AdjustmentFlag DESC),
UnmatchedOrder = CASE WHEN EXISTS(SELECT 1 FROM [Order] uo WHERE uo.OrderId = o.OrderId GROUP BY uo.OrderId HAVING(COUNT(uo.OrderId) = 1)) THEN 1 ELSE 0 END,
OriginalWithoutAdjustment = CASE WHEN EXISTS(SELECT 1 FROM [Order] uo WHERE uo.OrderId = o.OrderId AND uo.Amount = o.Amount GROUP BY uo.OrderId, uo.Amount HAVING (MAX(uo.AdjustmentFlag) = 1)) THEN 1 ELSE 0 END,
AdjustmentWithoutOriginal = CASE WHEN EXISTS(SELECT 1 FROM [Order] uo WHERE uo.OrderId = o.OrderId AND uo.Amount = o.Amount GROUP BY uo.OrderId, uo.Amount HAVING (MIN(uo.AdjustmentFlag) = 1)) THEN 1 ELSE 0 END
FROM [Order] o
)
,MatchedOrders AS
(
SELECT
Id
FROM Orders
WHERE
-- Assume AdjustmentFlag = 2 and take everything else
EffectiveOrder <> 1
OR
(
-- Assume AdjustmentFlag = 2 and there is no Order with AdjustmentFlag = 0
-- Take everything since the MIN AdjustmentFlag = 1
AdjustmentWithoutOriginal = 1
AND EffectiveOrder > 1
)
OR
(
-- Assume AdjustmentFlag = 1 and there are no other Orders, so ignore it
AdjustmentFlag = 1
AND UnmatchedOrder = 1
)
OR
(
-- We don't care about the orders if they don't have any Amount
Amount = 0
AND EffectiveOrder = 1
)
AND NOT
(
-- We have an Original without any other Orders
EffectiveOrder = 1
AND UnmatchedOrder = 1
AND AdjustmentFlag = 0
)
)
SELECT
o.OrderId,
o.AdjustmentFlag,
o.Amount,
o.EffectiveOrder,
o.UnmatchedOrder,
Excluded = CASE WHEN mo.Id IS NULL THEN 0 ELSE 1 END
FROM Orders o
LEFT OUTER JOIN MatchedOrders mo
ON o.Id = mo.Id
ORDER BY OrderId, Amount, AdjustmentFlag
结果:
答案 0 :(得分:2)
尝试:
with cte as
(select o.*,
case AdjustmentFlag when 1 then -1 else 1 end DrCr,
row_number() over (partition by OrderId, Amount, case AdjustmentFlag when 1 then 1 end
order by AdjustmentFlag, Id) Rn
from [Order] o)
select OrderId,
max(case DrCr when 1 then Id end) DrId,
sum(case DrCr when 1 then Amount else 0 end) DrAmount,
max(case DrCr when 1 then AdjustmentFlag end) DrAdjustmentFlag,
max(case DrCr when -1 then Id end) CrId,
sum(case DrCr when -1 then Amount else 0 end) CrAmount,
max(case DrCr when -1 then AdjustmentFlag end) CrAdjustmentFlag,
sum(DrCr * Amount) BalanceAmount
from cte
group by OrderId, Amount, Rn
having sum(DrCr * Amount) >= 0 /* excludes unmatched cancelled orders */
- 如果您只想查看不匹配的原始/修订订单,请将having
子句条件更改为> 0
。
SQLFiddle here。