【问题标题】:SELECT returning multiple rows as stringSELECT 以字符串形式返回多行
【发布时间】:2012-02-20 09:45:26
【问题描述】:

我有一张桌子:

合同:

contractid | contract name
"1" | "MAG:001"
"2" | "MAG:002"

-- 和--

设备:

devid | serialnum | fk_contractid
10 | 1234 | 1
11 | 5678 | 1
12 | 4321 | 2
13 | 8765 | 2

devices.fk_contractid =contracts.contractid

我需要选择会给出结果的选择:

"MAG:001" | 1234, 5678
"MAG:002" | 4321, 8765

如何在 PL-SQL 中做到这一点?

【问题讨论】:

  • “合约名称”列中是否真的有空格,顺便说一句? :)

标签: sql oracle plsql string-aggregation


【解决方案1】:

假设 11g(引入listagg 时):

  select    CONTRACT_NAME
         || '|'
         || LISTAGG(D.SERIALNUM, ',') within group (order by CONTRACTID)
    from CONTRACTS C join DEVICES D on D.FK_CONTRACTID = C.CONTRACTID
group by CONTRACT_NAME

【讨论】:

    【解决方案2】:

    如果你有 10g 而不是 11g,则有一个类似于 LISTAGG 的隐藏函数。

    WMSYS.WM_CONCAT

    SELECT Contracts.contract_name
         , WMSYS.WM_CONCAT(Devices.serialnum)
      FROM Contracts, Devices
     WHERE Contracts.contractid = Devices.fk_contractid
     GROUP BY Contracts.contract_name;
    

    WM_CONCAT 不允许您排序。

    您也可以像这样创建自己的函数:

    FUNCTION concat_serialnum(the_contract Contracts.contractid%TYPE)
     RETURN VARCHAR2
    IS
      return_value VARCHAR2(4000);
      CURSOR serials_cur IS
        SELECT serialnum
          FROM Devices
          WHERE contractid = the_contract
          ORDER BY serialnum;
    BEGIN
      FOR serials_rec IN serials_cur LOOP
        return_value := return_value || ', ' || serials_rec.serialnum;
      END LOOP;
      RETURN LTRIM(return_value, ', ');
    END concat_serialnum;
    

    您应该添加代码来处理 4,000 个字符的限制。

    您的查询现在是

    SELECT contract_name
         , concat_serialnum(contractid)
      from Contracts;
    

    【讨论】:

    • +1,但在使用 wm_concat 时不需要指定架构。我相信就像所有dbms_...函数一样,它有一个公共同义词。
    【解决方案3】:

    做这样的事情:

    SELECT '"' || c.contract_name || '"'
    ...
    FROM contracts c INNER JOIN devices d ON d.fk_contractid = c.contractid
    

    添加您需要的列 - 使用双栏(我似乎记得)连接字符串。

    您需要进行试验以了解如何获取引号 - 可以用单引号提供,也可以用双引号提供,引号以某种方式转义。

    【讨论】:

    • 呸,我刚刚注意到您希望在同一个字符串中有多行。 Oracle 文档中应该有多行函数。
    【解决方案4】:

    如果你没有使用 11g 并且不能使用@John Doyle 的解决方案,那么你可以创建自己的aggregate function

    如果你不怕性能问题,那么你可以尝试使用xmlagg作为聚合函数,然后格式化,即:

    select contract_name,
           rtrim(xmlagg(xmlelement(e, serialnum || ',')).extract('//text()')) as serialnums
      from contracts, devices
     where contractId = fk_contractid
     group by contract_name
    

    (没查过)

    【讨论】:

      猜你喜欢
      • 2021-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-03
      • 2015-04-02
      • 2016-11-23
      相关资源
      最近更新 更多