How to concatenate text from multiple rows into a single text string in Oracle server?
Have you tried this?
select end_date,
listagg(CLOSE_DATE, ',') within group (order by CLOSE_DATE DESC) as close_dates,
listagg(id, ',') within group (order by id) as ids
from TBL_S_PLCLOSEDATE
where D_END = date '2018-05-18'
group by end_date;
How to concatenate text from multiple rows into a single text string in SQL Server
If you are on SQL Server 2017 or Azure, see Mathieu Renda answer.
I had a similar issue when I was trying to join two tables with one-to-many relationships. In SQL 2005 I found that XML PATH
method can handle the concatenation of the rows very easily.
If there is a table called STUDENTS
SubjectID StudentName
---------- -------------
1 Mary
1 John
1 Sam
2 Alaina
2 Edward
Result I expected was:
SubjectID StudentName
---------- -------------
1 Mary, John, Sam
2 Alaina, Edward
I used the following T-SQL
:
SELECT Main.SubjectID,
LEFT(Main.Students,Len(Main.Students)-1) As "Students"
FROM
(
SELECT DISTINCT ST2.SubjectID,
(
SELECT ST1.StudentName + ',' AS [text()]
FROM dbo.Students ST1
WHERE ST1.SubjectID = ST2.SubjectID
ORDER BY ST1.SubjectID
FOR XML PATH (''), TYPE
).value('text()[1]','nvarchar(max)') [Students]
FROM dbo.Students ST2
) [Main]
You can do the same thing in a more compact way if you can concat the commas at the beginning and use substring
to skip the first one so you don't need to do a sub-query:
SELECT DISTINCT ST2.SubjectID,
SUBSTRING(
(
SELECT ','+ST1.StudentName AS [text()]
FROM dbo.Students ST1
WHERE ST1.SubjectID = ST2.SubjectID
ORDER BY ST1.SubjectID
FOR XML PATH (''), TYPE
).value('text()[1]','nvarchar(max)'), 2, 1000) [Students]
FROM dbo.Students ST2
How can multiple rows be concatenated into one in Oracle without creating a stored procedure?
There are many way to do the string aggregation, but the easiest is a user defined function. Try this for a way that does not require a function. As a note, there is no simple way without the function.
This is the shortest route without a custom function: (it uses the ROW_NUMBER() and SYS_CONNECT_BY_PATH functions )
SELECT questionid,
LTRIM(MAX(SYS_CONNECT_BY_PATH(elementid,','))
KEEP (DENSE_RANK LAST ORDER BY curr),',') AS elements
FROM (SELECT questionid,
elementid,
ROW_NUMBER() OVER (PARTITION BY questionid ORDER BY elementid) AS curr,
ROW_NUMBER() OVER (PARTITION BY questionid ORDER BY elementid) -1 AS prev
FROM emp)
GROUP BY questionid
CONNECT BY prev = PRIOR curr AND questionid = PRIOR questionid
START WITH curr = 1;
SQL Query to concatenate column values from multiple rows in Oracle
There are a few ways depending on what version you have - see the oracle documentation on string aggregation techniques. A very common one is to use LISTAGG
:
SELECT pid, LISTAGG(Desc, ' ') WITHIN GROUP (ORDER BY seq) AS description
FROM B GROUP BY pid;
Then join to A
to pick out the pids
you want.
Note: Out of the box, LISTAGG
only works correctly with VARCHAR2
columns.
Oracle - SQL to concatenate multiple rows
If you have Oracle 11g you could use the LISTAGG() function for this:
SELECT
id
, listagg(str) WITHIN GROUP (ORDER BY OFFSET) AS str_of_str
FROM yourtable
GROUP BY id
see: http://docs.oracle.com/cd/E11882_01/server.112/e10592/functions089.htm
and this sqlfiddle
| ID | STR_OF_STR |
|----|--------------------------|
| 1 | TestSTR1TestSTR3TestSTR5 |
| 2 | TestSTR4TestSTR2 |
| 3 | TestSTR6 |
combine multiple rows into a single row in Oracle?
The function that you need is listagg()
with does string concatenation when aggregating. You also need to first concatenate the ids together:
select id,
listagg(m_id || ',' || s_m_id, ';') within group (order by m_id) as merge_ids
from test t
group by id;
By the way, the result data is incorrect (because the id is the same on all three rows). This probably accounts for the downvote.
EDIT (in response to comment):
You have two separators in the original example, one is comma (between ids) and one is a semicolon (between rows). You can replace either with '|'
to get a pipe separator.
Concatenate across columns and rows using group and listagg in Oracle SQL
Use the following query where you will directly get concatenated column values:
SELECT
"GROUP",
LISTAGG(VAL_1 || VAL_2 || VAL_3)
WITHIN GROUP(ORDER BY VAL_1) AS "TEXT"
FROM DATA
GROUP BY "GROUP";
Note: Do not use oracle reserved keywords as the column names. Here GROUP
is the oracle reserved keyword.
Cheers!!
Concatenate and group multiple rows in Oracle
Consider using LISTAGG function in case you're on 11g:
select grp, listagg(name,',') within group( order by name )
from name_table group by grp
sqlFiddle
upd: In case you're not, consider using analytics:
select grp,
ltrim(max(sys_connect_by_path
(name, ',' )), ',')
scbp
from (select name, grp,
row_number() over
(partition by grp
order by name) rn
from tab
)
start with rn = 1
connect by prior rn = rn-1
and prior grp = grp
group by grp
order by grp
sqlFiddle
How to combine all records into one row | ORACLE SQL |
Here's one way, using LISTAGG to illustrate the method. If you have too many tables, you will need a different way of aggregating (such as XMLAGG), but that's a different issue - you can find hundreds of questions about that here on SO.
Best to use UNION ALL rather than UNION, but if you insist on just UNION, you can modify the solution yourself. Use LISTAGG, but don't include UNION [ALL] in the tokens to be aggregated; rather, use it as the delimiter!
For easier reading of the output, I included a newline in the delimiter as well; that's not needed except for debugging. You may choose to remove it after you are satisfied that the query works as expected.
Also, I didn't bother to concatenate a semicolon at the end; you can add that yourself.
NOTE - the output is a single row, meaning a single string that contains newline characters (and therefore appears as multiple lines of text). It's NOT spread over multiple rows, it's just several lines in a single string in a single row.
EDIT Looking at it again, I see that your individual SELECT statements are incorrect (they show the keyword "from" twice, and all SELECT statements are counting the rows in the get_tables
table instead of in each respective table, and perhaps other mistakes as well). I will let you fix all those mistakes; they are unrelated to the main topic of your question, which was about aggregating the statements - whether correct or otherwise - in the desired way.
END EDIT (FURTHER EDIT AT THE BOTTOM OF THE ANSWER)
with get_tables (tbl_names) as (
select 'EMP_1' from dual union all
select 'EMP_2' from dual union all
select 'STUD_1' from dual union all
select 'STUD_2' from dual union all
select 'STUD_3' from dual union all
select 'STUDENT_DETAILS' from dual
)
-- end of sample data, for testing only; remove WITH clause
-- and use your actual table and column names.
select listagg('SELECT ' || '''' || tbl_names || '''' ||
' AS TBL , COUNT(*) as CNT FROM from tbl_names',
' union all' || chr(10))
within group (order by tbl_names) as sql_str
from get_tables;
SQL_STR
----------------------------------------------------------------------------------
SELECT 'EMP_1' AS TBL , COUNT(*) as CNT FROM from tbl_names union all
SELECT 'EMP_2' AS TBL , COUNT(*) as CNT FROM from tbl_names union all
SELECT 'STUDENT_DETAILS' AS TBL , COUNT(*) as CNT FROM from tbl_names union all
SELECT 'STUD_1' AS TBL , COUNT(*) as CNT FROM from tbl_names union all
SELECT 'STUD_2' AS TBL , COUNT(*) as CNT FROM from tbl_names union all
SELECT 'STUD_3' AS TBL , COUNT(*) as CNT FROM from tbl_names
SECOND EDIT
The OP's use case requires the generation of a CLOB, so LISTAGG won't work. Here's how the query can be modified to work for CLOB output. I corrected the statement at the same time - see my first EDIT, before the first code block.
To make sure this works correctly, I wrote it for the ALL_TABLES
view in my schema; the table names are in a column called TABLE_NAME
. The OP should change these names for his use case.
select regexp_replace(
xmlcast(xmlagg(xmlelement(e,
'select ''' || table_name || ''' as tbl, count(*) as cnt from '
|| table_name, ' union all ' || chr(10))) as clob),
' union all ' || chr(10) ||'$', ';')
as sql_string
from all_tables;
END SECOND EDIT
Related Topics
Access SQL Query to Concatenate Rows
Differencebetween ";" and "Go" in T-Sql
Postgresql: Check If Schema Exists
Vb.Net Escape Reserved Keywords in SQL Statement
How to Emulate Tagged Union in a Database
SQL Server:Check If Variable Is Empty or Null for Where Clause
What Is Wrong with a Transitive Dependency
Insert Xml into SQL Server 2008 Database
How to Upsert Multiple Rows with Individual Values in One Statement
Conditional SQLite Check Constraint
Combine Multiple Rows into Multiple Columns Dynamically in SQL Server
How to Generate a Random, Unique, Alphanumeric Id of Length N in Postgres 9.6+
Oracle Display More Than 24 Hours
Inserting Data into a Temporary Table
Mysql: Select N Rows, But with Only Unique Values in One Column