SELECT将多行作为字符串返回

时间:2012-02-20 09:45:26

标签: sql oracle plsql string-aggregation

我有一张桌子:

合同:

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中完成?

4 个答案:

答案 0 :(得分:4)

假设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

答案 1 :(得分:3)

如果你有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;

答案 2 :(得分:0)

做这样的事情:

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

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

您需要尝试查看如何获得引号 - 以单引号提供,或以引号标记以某种方式转义的双引号。

答案 3 :(得分:0)

如果你没有使用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

(没检查)

相关问题