我有一张桌子:
合同:
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中完成?
答案 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
(没检查)