2012-02-20 23 views
0

我有一個表:SELECT返回多個行作爲字符串

合同:

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

是否列「合同名稱」真的有它的空間,順便說一句? :) – halfer 2012-02-20 09:56:23

回答

0

做這樣的事情:

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

添加你需要的列 - 使用雙欄(我似乎記得)來連接字符串。

您需要試驗一下,看看如何得到一個引號 - 要麼用單引號提供,要麼用雙引號將引號以某種方式轉義。

+0

Bah,我只是注意到你想在同一個字符串中有多行。 Oracle文檔中應該有多行功能。 – halfer 2012-02-20 09:57:37

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 
0

如果你不使用11g和不能使用@約翰·道爾的解決方案,那麼你就可以創建自己的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 

(沒有檢查)

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; 

您應該添加代碼以處理4000個字符的限制。

您的查詢現在是

SELECT contract_name 
    , concat_serialnum(contractid) 
    from Contracts; 
+0

+1,但在使用'wm_concat'時不需要指定模式。我**相信**這裏有一個公共同義詞,就像所有'dbms _...'函數一樣。 – Ben 2012-02-20 20:13:39