【问题标题】:How to Use COLLECT with VARCHAR2 Oracle 10g如何将 COLLECT 与 VARCHAR2 Oracle 10g 一起使用
【发布时间】:2016-05-24 20:44:19
【问题描述】:

我正在尝试让 COLLECT 功能为我工作。我使用的是 10g,因此发现 LISTAGG 和 WM_CONCAT 不起作用(无效标识符错误)。我拥有的数据例如如下。

Order  Lot
123    A23088
123    A23089
089    AABBCC
305    120848
305    CCDDYY

我需要返回的内容如下

Order   Lot
123     A23088, A23089
089     AABBCC
305     120848, CCDDYY

使用以下内容,我得到错误:TO_STRING is an invalid identifier

TO_STRING ( CAST(COLLECT(DISTINCT LOT) AS varchar2(100)) ) AS LOT

使用以下内容,我得到了错误:预期的 CHAR“不一致的数据类型:预期的 %s 得到了 %s”

TO_CHAR ( CAST(COLLECT(DISTINCT LOT) AS varchar2(100)) ) AS LOT

使用以下内容,我收到错误:预期的 NUMBER“不一致的数据类型:预期的 %s 得到了 %s”

COLLECT(DISTINCT WHSE_LOT)

有什么方法可以让这个功能为我工作吗?

【问题讨论】:

    标签: sql oracle10g collect listagg


    【解决方案1】:

    collect function 创建一个嵌套表,在您的情况下是一个字符串表,然后您将其转换为特定类型 - 即定义为 varchar2 表的类型。您不能转换为单个字符串。

    有一些众所周知的字符串聚合技术列表,like this one。有一个that uses collect,但你仍然需要表格类型和一个函数来将生成的表格转换为分隔字符串。

    逐字复制该示例:

    CREATE OR REPLACE TYPE t_varchar2_tab AS TABLE OF VARCHAR2(4000);
    /
    
    CREATE OR REPLACE FUNCTION tab_to_string (p_varchar2_tab  IN  t_varchar2_tab,
                                              p_delimiter     IN  VARCHAR2 DEFAULT ',') RETURN VARCHAR2 IS
      l_string     VARCHAR2(32767);
    BEGIN
      FOR i IN p_varchar2_tab.FIRST .. p_varchar2_tab.LAST LOOP
        IF i != p_varchar2_tab.FIRST THEN
          l_string := l_string || p_delimiter;
        END IF;
        l_string := l_string || p_varchar2_tab(i);
      END LOOP;
      RETURN l_string;
    END tab_to_string;
    /
    

    使用该类型和功能,您可以:

    SELECT tab_to_string(CAST(COLLECT(DISTINCT lot) AS t_varchar2_tab)) AS lot FROM ...
    

    有趣的是,the 10g version of collect 不支持DISTINCT;它不会抱怨(!?),但会留下重复。

    您可以通过the set function 传递集合以删除重复项:

    SELECT tab_to_string(SET(CAST(COLLECT(DISTINCT lot) AS t_varchar2_tab))) AS lot FROM ...
    

    在 10.2.0.5 中运行快速演示:

    create table table1(order_no number, lot varchar2(10));
    
    insert into table1 values (590288, '2016538');
    insert into table1 values (590288, '2016535');
    insert into table1 values (590288, '6016535');
    insert into table1 values (590288, '2016535');
    insert into table1 values (590288, '2016538');
    
    SELECT order_no, tab_to_string(SET(CAST(COLLECT(DISTINCT lot) AS t_varchar2_tab))) AS LOT
    FROM table1 WHERE order_no = 590288 GROUP BY order_no;
    
      ORDER_NO LOT                                              
    ---------- --------------------------------------------------
        590288 2016538,2016535,6016535                           
    

    【讨论】:

    • 感谢@AlexPoole 的帮助。我发现这个解决方案适用于一个例外 - 不仅仅是返回不同的值。例如,SELECT order_no, tab_to_string(CAST(COLLECT(DISTINCT lot) AS t_varchar2_tab)) AS LOT FROM table1 WHERE order_no = 590288 GROUP BY order_no; Returns Order_No Lot 590288 2016535,2016535,6016535,2016538,2016538 有什么建议吗?
    • @ESC - 更新为通过 SET() 传递集合以删除 suplicates,因为 10g 无法识别 COLLECT(DISTINCT ...)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-26
    • 2010-11-05
    • 2010-12-23
    • 2013-06-29
    • 1970-01-01
    • 1970-01-01
    • 2017-01-17
    相关资源
    最近更新 更多