我試圖實施借記貸記解決方案系統,但是我很難根據集合表達邏輯。在SQL查詢中實施借記貸記解決方案系統
假設我有訂單的表:
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
S中的仍然是基於他們是否有匹配的「取消」標誌有效。
0 - Original Order
1 - Cancelled Order
2 - Adjusted Order
- 甲
1
匹配0
或偏好2
到0
。 - A
1
如果標誌不匹配,則忽略該標誌。
鑑於上面的例子:
- 編號2將匹配ID 1留下標識3.
- ID 4將匹配或者ID 5或ID 6但不是兩者。
- Id 7將被忽略。
- Id 10將匹配Id 8或Id 9,但不是兩者都匹配。
- ID 12將匹配ID 11.
- ID 14將匹配Id 13或Id 15,但不是兩者都匹配。
- Id 16將被忽略。
可能的結果是[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
結果:
對於同一OrderId,取消訂單的金額是否總是與原始金額或調整後訂單的金額完全一致?您可以爲同一OrderId有多個取消的訂單記錄嗎? –
是取消的訂單必須完全匹配。是的,可以有多個取消訂單,我會發佈一個示例。 – Romoku
我曾經工作過的地方叫做和解。 – Jodrell