|
在oracle中,该LISTAGG函数允许我将其与OVER (PARTITION BYcolumn..)一起使用子句。但是,它不支持使用带有ROWS或RANGE关键字窗口。
" F0 r- g3 F/ z- S" \7 u我有一个来自商店寄存器的数据集(简化了这个问题)。请注意,寄存器表的数量总是1-一个,一个交易行。
0 U3 E% @; f/ D1 v6 MTranID TranLine ItemId OrderID Dollars Quantity------ -------- ------ ------- ------- -------- 101 238455 233 23 .99 11 102 23845 23845 23 23 22.99 11 103 23845 23 2.99 11 104 23845 2335 23 22.99 11 105 23845 2335 23 22.99 1我必须将这些数据匹配到特殊订购系统中的表中。在这个系统中,项目按数量分组。请注意,该系统可以在多行中拥有相同的项目ID(即使项目相同,订购的组件也可能不同)。
5 B. ~" }) F- XItemId OrderID Order Line Dollars Quantity------ ------- ---------- ------- --------23845 233 88 8885 88885 .323845 2333 55 555 5555.98 2我可以匹配这个数据 唯一 方法是按订单ID,商品ID匹配美元金额。$ k# q9 N Y+ i: f3 H
本质上,我需要得到以下结果。
" N# d3 U$ r7 P1 EItemId OrderID Order Line Dollars Quantity Tran ID Tran Lines------ ------- ---------- ------- -------- ------- ----------23845 233 88 8885 88885 .102;10323845 23 555.105 我不太在意tran我只关心美元金额是否匹配,我在计算特殊订单总数时不会重用寄存器中的一行。我不需要tran行分解成表-. w' z3 d$ e/ n- `
这是为了报告,粒度永远不会降低到寄存器事务行的水平。7 D n' B9 h; n6 O8 V" u
我最初的想法是,我可以使用分析函数来实现最佳匹配,以识别与订单系统中的美元数量和数量相匹配的第一行,以获得以下结果集:
. M' k+ \0 F5 QTranID TranLine ItemId OrderID Dollars Quantity CumDollar CumQty------ -------- ------ ------- ------- -------- -------- ------ 101 238455 233 23 .99 1 2.99 11 102 238845 23845 23 23 .99 1 555 555 555555 555555 555555555 555555 5555555555555555555 55555555555555555 55555555555555555555555 55555555555555555555555 5555555555555555555555 .88 21 103 23845 23845 23 22.99 1 88 88 88 888 888.97 31 104 23845 23845 23 23 22. 11111 .1055 23845 235 2385 23 22.99 1 144.95 5到目前为止,一切都很好。但是,然后我试着LISTAGG添加到我的查询中:
+ B+ `# d, ]- [" ]: xSELECT tranid,tranline,itemid,orderid,dollars,quantity, SUM(dollars) OVER (partition by tranid,itemid,orderid order by tranline) cumdollar, SUM(quantity) OVER (partition by tranid,itemid,orderid order by tranline) cumqty LISTAGG (tranline) within group (order by tranid,itemid,orderid,tranline) OVER (partition by tranid,itemid,orderid)FROM table我发现它总是回到完整agg而不是积累agg:
( n8 ^. K* A7 {: OTranID TranLine ItemId OrderID Dollars Quantity CumDollar CumQty ListAgg------ -------- ------ ------- ------- -------- -------- ------ ------- 101 238455 233 23 .99 1 2.102;103;104;1051;1051;1051;102,102,102,102,1051,102,102,23845,23102,102、102、102、102、23845、23、23、23、23.99 1 5.102;103;104;1051;1051;1051103,1051,103,103,103,103,103,103,103,103,103,103,103,103,23845,23,23,23.99 1 88 88 88 888 888.102;103;104;1051;1051;1051;104;10511051;104;104 23845 23 235. 11111 .102;103;104;1051;1051;1051;105;105;105;105;105;105; 23845.99 1 144.102;103;104;105所以,这没用。2 L- C1 s& {0 u% l p: n
如果可能的话,我更愿意在SQL执行此操作。我知道我可以用游标和过程逻辑来做到这一点。
( T. A+ R; c$ Y( l0 i: u, d1 h用什么方法?LISTAGG窗口化的分析功能,还是可以使用其他支持该功能的分析功能?/ x! [& J# U4 P+ @& g! }
我正在使用11gR2。% |5 W- j' A4 Y" u1 u5 q; N% y& X; b
8 B2 n4 h' W, D H( e' r* ~
解决方案:
* X: g& p# L- Y 唯一能想到的方法就是用相关子查询:1 y9 C, V3 W2 [5 t* m
WITH CTE AS( SELECT TranID, TranLine, ItemID, OrderID, Dollars, Quantity, SUM(dollars) OVER (PARTITION BY TranID,ItemID,OrderID ORDER BY TranLine) AS CumDollar, SUM(Quantity) OVER (PARTITION BY TranID,ItemID,OrderID ORDER BY TranLine) AS CumQuantity FROM T)SELECT TranID, TranLine, ItemID, OrderID, Dollars, Quantity, CumDollar, CumQuantity, SELECT LISTAGG(Tranline,';') WITHIN GROUP(ORDER BY CumQuantity) FROM CTE T2 WHERE T1.CumQuantity >= T2.CumQuantity AND T1.ItemID = T2.ItemID AND T1.OrderID = T2.OrderID AND T1.TranID = T2.TranID GROUP BY tranid,itemid,orderid AS ListAggFROM CTE T1;我意识到这不能提供你需要的确切输出,但我希望它足以克服积累LISTAGG问题并帮你一臂之力。" ]9 G9 X# t, u/ ?' y A
我已经设置了一个SQL Fiddle演示解决方案。 |
|