当前位置: 首页 > 面试题库 >

与窗口子句等效的LISTAGG

武晨
2023-03-14
问题内容

在oracle中,该LISTAGG函数允许我将其与OVER (PARTITION BY column..)子句一起使用。但是,它不支持使用带有ROWSRANGE关键字的窗口。

我有一个来自商店寄存器的数据集(针对该问题进行了简化)。请注意,寄存器表的数量始终为1-一项,一条交易行。

TranID TranLine ItemId OrderID Dollars Quantity
------ -------- ------ ------- ------- --------
1      101      23845  23      2.99    1
1      102      23845  23      2.99    1
1      103      23845  23      2.99    1
1      104      23845  23      2.99    1
1      105      23845  23      2.99    1

我必须将此数据“匹配”到特殊订购系统中的表,在该系统中,项目按数量分组。请注意,系统可以在多行上具有相同的项目ID(即使项目相同,订购的组件也可能不同)。

ItemId OrderID Order Line Dollars Quantity
------ ------- ---------- ------- --------
23845  23      1          8.97    3
23845  23      2          5.98    2

我可以匹配此数据的 唯一 方法是按订单ID,商品ID和美元金额进行匹配。

本质上,我需要得到以下结果。

ItemId OrderID Order Line Dollars Quantity Tran ID  Tran Lines
------ ------- ---------- ------- -------- -------  ----------
23845  23      1          8.97    3        1        101;102;103
23845  23      2          5.98    2        1        104;105

我并不特别在意tran行是否以任何方式排序,我只关心美元金额是否匹配,并且我在计算特殊订单的总数时不“重用”寄存器中的一行。我不需要将tran行分解成一个表-
这是出于报告目的,并且粒度永远不会下降到寄存器事务行级别。

我最初的想法是,我可以使用解析函数来做到“最佳匹配”,以识别与订购系统中的美元数量和数量相匹配的第一行,从而得到如下结果集:

TranID TranLine ItemId OrderID Dollars Quantity CumDollar  CumQty
------ -------- ------ ------- ------- -------- --------   ------
1      101      23845  23      2.99    1        2.99       1
1      102      23845  23      2.99    1        5.98       2
1      103      23845  23      2.99    1        8.97       3
1      104      23845  23      2.99    1        11.96      4
1      105      23845  23      2.99    1        14.95      5

到目前为止,一切都很好。但是,然后我尝试将LISTAGG添加到我的查询中:

SELECT 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:

TranID TranLine ItemId OrderID Dollars Quantity CumDollar  CumQty ListAgg
------ -------- ------ ------- ------- -------- --------   ------ -------
1      101      23845  23      2.99    1        2.99       1      101;102;103;104;105
1      102      23845  23      2.99    1        5.98       2      101;102;103;104;105
1      103      23845  23      2.99    1        8.97       3      101;102;103;104;105
1      104      23845  23      2.99    1        11.96      4      101;102;103;104;105
1      105      23845  23      2.99    1        14.95      5      101;102;103;104;105

因此,这没有用。

如果可能的话,我更愿意在SQL中执行此操作。我知道我可以使用游标和过程逻辑来做到这一点。

有什么方法可以使用LISTAGG分析功能进行窗口化,或者是否可以使用其他支持此功能的分析功能进行窗口化?

我正在使用11gR2。


问题答案:

我能想到的唯一方法是使用相关子查询:

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 ListAgg
FROM    CTE T1;

我意识到这并不能提供您所需要的确切输出,但是希望它足以克服累积LISTAGG的问题并助您一臂之力。

我已经设置了一个SQL Fiddle来演示该解决方案



 类似资料:
  • 似乎 WITH 仅在 Sybase SQL Anywhere 中受支持:http://dcx.sybase.com/1100/en/dbusage_en11/commontblexpr-s-5414852.html …但不在Sybase ASE中:( 有人可以建议Sybase ASE中是否存在等效的构造吗?还有其他方法可以实现东西而不是使用 WITH,但我们计划重新调整一些动态生成的 SQL 的用

  • 问题内容: 我是MySql的新手,所以请保持谦虚。 Oracle 中的子句或MySQL中的SQL Server中的表是否等效?我想做的是以下几点: 从表A删除一组行 将已删除的行集插入表B。 请帮忙! 谢谢 问题答案: 不幸的是,您不能在 一个查询中 同时进行插入和删除 操作 ,但是如果您使用的是事务存储引擎(例如InnoDB),则可以在一个 事务中 完成所有操作。此外,它受Oracle和Post

  • 操纵子窗口 进程:渲染进程​ 使用 window.open 创建一个新窗口时,会自动创建一个 BrowserWindowProxy 的实例将返回一个标识,可通过标识对这个新窗口进行少量功能的控制. 实例方法 BrowserWindowProxy对象具有以下实例方法: win.blur() 用途:从子窗口中去焦 win.close() 用途:强制关闭子窗口,而不调用其卸载事件(unload even

  • 问题内容: 我一直在大量阅读有关SQL SERVER LIMIT子句的替代方法。太令人沮丧了,他们仍然拒绝适应它。无论如何,我真的没办法解决这个问题。我要转换的查询是这样的… 任何帮助将不胜感激,谢谢。 问题答案: 在SQL Server 2012中,支持ANSI标准/ 语法。我在博客上发表了这篇文章,这是官方文档(这是的扩展)。为SQL Server 2012转换的语法为: 在此之前,您需要使用

  • 问题内容: 我可以在C#中做到这一点: 例如在Java中 我如何查询这样的ArrayList?谢谢。 问题答案: Java 8引入了Stream API ,该API允许与Linq中的构造类似的构造。 例如,您的查询可以表示为: 如果存在默认值,您显然需要锻炼,在这种情况下,这似乎很奇怪,但是我已经展示了它,因为这就是您问题中的代码所做的。

  • pre { white-space: pre-wrap; } Layout 组件可以内嵌在窗口(window)中。我们可以创建一个复杂的布局窗口,甚至不需要写任何的 js 代码。jquery-easyui 框架帮我们在后台做渲染和调整尺寸。 作为一个实例,我们创建一个窗口(window),它包含两个部分,一个放置在左边一个放置在右边。在窗口(window)的左边我们创建一个树形菜单(tree),在