[英]Using Oracle SQL, how can I concatenate data from multiple rows into one row without using PIVOT, LISTAGG or custom built functions?
I'm using Oracle SQL.我正在使用 Oracle SQL。 This is the table:
这是表格:
doc-nr ![]() |
code![]() |
text![]() |
---|---|---|
0000010 ![]() |
155 ![]() |
Sample text from code 155![]() |
0000010 ![]() |
455 ![]() |
Sample text1 from code 455![]() |
0000010 ![]() |
455 ![]() |
Sample text2 from code 455![]() |
0000010 ![]() |
455 ![]() |
Sample text3 from code 455![]() |
With this query:使用此查询:
SELECT t155.text as "155", t455.text as "455"
FROM myTable t155
JOIN myTable t455 ON t155.doc-nr = t455.doc-nr
WHERE t155.code = '155'
AND t455.code = '455'
I get ugly result:我得到丑陋的结果:
155 ![]() |
455 ![]() |
---|---|
Sample text from code 155![]() |
Sample text1 from code 455![]() |
Sample text from code 155![]() |
Sample text2 from code 455![]() |
Sample text from code 155![]() |
Sample text3 from code 455![]() |
I want the output to be one row:我希望 output 是一行:
155 ![]() |
455 ![]() |
455 ![]() |
455 ![]() |
---|---|---|---|
Sample text from code 155![]() |
Sample text1 from code 455![]() |
Sample text2 from code 455![]() |
Sample text3 from code 455![]() |
Or:或者:
155 ![]() |
455 ![]() |
---|---|
Sample text from code 155![]() |
Sample text1 from code 455;![]() ![]() ![]() |
How can you do this with Oracle SQL without using PIVOT or LISTAGG or using custom built functions?在不使用 PIVOT 或 LISTAGG 或使用自定义构建函数的情况下,如何使用 Oracle SQL 做到这一点?
You can create such a function returning SYS_REFCURSOR
in order to pivot your data dynamically您可以创建这样的 function 返回
SYS_REFCURSOR
以便动态地 pivot 您的数据
CREATE OR REPLACE FUNCTION Get_Pivoted_Cols RETURN SYS_REFCURSOR IS
v_recordset SYS_REFCURSOR;
v_sql VARCHAR2(32767);
v_cols1 VARCHAR2(32767);
v_cols2 VARCHAR2(32767);
BEGIN
SELECT LISTAGG( ''''||rn||''' AS "'||rn||'"' , ',' ) WITHIN GROUP ( ORDER BY text ),
LISTAGG( 'MAX("'||rn||'") AS "'||rn||'"' , ',' ) WITHIN GROUP ( ORDER BY text )
INTO v_cols1, v_cols2
FROM
( SELECT code||'_'||ROW_NUMBER() OVER (PARTITION BY doc_nr, code ORDER BY text) AS rn, t.*
FROM tab t );
v_sql :='SELECT '||v_cols2||
' FROM
(
SELECT code||''_''||ROW_NUMBER() OVER (PARTITION BY doc_nr, code ORDER BY text) AS rn, t.*
FROM tab t
)
PIVOT
(
MAX(text) FOR rn IN ( '|| v_cols1 ||' )
)
GROUP BY doc_nr';
OPEN v_recordset FOR v_sql;
DBMS_OUTPUT.PUT_LINE(v_sql);
RETURN v_recordset;
END;
which will generate this output as a SQL statement这将生成此 output 作为 SQL 语句
SELECT MAX("155_1") AS "155_1",
MAX("455_1") AS "455_1",
MAX("455_2") AS "455_2",
MAX("455_3") AS "455_3"
FROM
(
SELECT code||'_'||ROW_NUMBER() OVER (PARTITION BY doc_nr, code ORDER BY text) AS rn,
t.*
FROM tab t
)
PIVOT
(
MAX(text) FOR rn IN ( '155_1' AS "155_1", '455_1' AS "455_1", '455_2' AS "455_2",
'455_3' AS "455_3" )
)
GROUP BY doc_nr;
and then run this code:然后运行此代码:
VAR rc REFCURSOR
EXEC :rc := Get_Pivoted_Cols;
PRINT rc
from SQL Developer's Command Line in order to see the result set.从SQL 开发人员的命令行中查看结果集。
If the problem is the size, you can use XML aggregation:如果问题是大小,可以使用 XML 聚合:
select mt.doc_nr, mt.text as text_155,
xmlquery('
for $i in .
return <e>{ fn:string-join($i/text, "; ") }</e>/text()'
passing tmp.xml
returning content
).getclobval() as text_455
from mytable mt
join (
select doc_nr, xmlagg(xmlelement("text", text)) as xml
from mytable
where code = 455
group by doc_nr
) tmp
on tmp.doc_nr = mt.doc_nr
where mt.code = 155
DOC_NR | TEXT_155 | TEXT_455
:------ | :------------------------ | :---------------------------------------------------------------------------------
0000010 | Sample text from code 155 | Sample text1 from code 455; Sample text3 from code 455; Sample text2 from code 455
db<>fiddle including the intermediate steps. db<>fiddle包括中间步骤。
Using xml functions in a such way is not good for performance (when there is more data) but in this case it works fine:以这种方式使用 xml 函数对性能不利(当有更多数据时),但在这种情况下它可以正常工作:
SELECT t155.text as "155",
sys_xmlagg(xmlelement(col, t455.text || ',')).extract('/ROWSET/COL/text()')
.getclobval() as "455"
FROM myTable t155
JOIN myTable t455
ON t155."doc-nr" = t455."doc-nr"
WHERE t155.code = '155'
AND t455.code = '455'
GROUP BY t155.text
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.