oracle pl/sql results into one string - sql

I'm trying to create a simple stored procedure that stores queried result into one string.
v_string1 varchar2(100);
Select column1
From dual;
Will return
column 1
--------
aaaa
bbbb
cccc
I want to store "aaaa, bbbb, cccc' into v_string1.
And all I can think of is a Cursor...
Is there a better way to handle this?

Using SQL Fiddle:
select LISTAGG(name, ',') WITHIN GROUP (ORDER BY 1) AS names
from temp_table

Another option using pure SQL that will work before Oracle 11G, although is still limited to 4000 characters for the string.
Select ltrim(max(names), ', ') as names
From (
Select sys_connect_by_path(name, ' ,') as names
From (
Select name, row_number() over (order by name) as rown
From temp_table
)
Start with rown = 1
Connect by rown = prior rown + 1
)

Related

Using query results as In clause parameter

I know I've seen this before, but can't come up with the search terms to find it.
I have a CTE returning a comma separated list from the below table:
Table
Create table Table
(
ID Number
, Name varchar2(100)
);
insert all
into Table (ID, Name) values (1, 'Alex')
into Table (ID, Name) values (2, 'Amy')
into Table (ID, Name) values (3, 'Jim')
select * from dual;
ID
Name
1
Alex
2
Amy
3
Jim
select substr(
listagg(Table.ID || ',') within group (order by null)
, 1
, length(listagg(Table.ID || ',') within group (order by null)) - 1
) IDs
from Table
where Name like 'A%'
Which gives me the results: 1,2
I'm trying to use this result in a query's in clause:
with CTE as
(
select substr(
listagg(tbl.ID || ',') within group (order by null)
, 1
, length(listagg(tbl.ID || ',') within group (order by null)) - 1
) IDs
from Table
where Name like 'A%'
)
select *
from Table
where cast(ID as varhcar2(1000)) in (select IDs from CTE) --Use results here
--believe the cast is required to compare, otherwise get a ORA-01722: invalid number
Which I want to return:
ID
Name
1
Alex
2
Amy
How can I use the CTE's resulting IDs string as the parameter of my in clause?
I'm afraid I don't understand your "problem". CTE is really strange; SUBSTR of something? Why? LISTAGG returns the same result anyway. Then you want to ... what? split that result so that you could use it in another query? As if you want to make it as complex as possible (and beyond) to solve something "simple". Therefore: what real problem are you trying to solve?
Anyway, here you go: you'll have to split aggregated string into rows if you want to use it in IN clause:
SQL> with CTE as
2 (select listagg(ID || ',') within group (order by null) IDs
3 from Test
4 where Name like 'A%'
5 )
6 select *
7 from Test
8 where id in (select regexp_substr(IDs, '[^,]+', 1, level)
9 from CTE
10 connect by level <= regexp_count(IDS, ',') + 1
11 );
ID NAME
---------- ----------
1 Alex
2 Amy
SQL>
The same result is returned by a simple
SQL> select *
2 from Test
3 where Name like 'A%';
ID NAME
---------- ----------
1 Alex
2 Amy
SQL>
That's why I asked: what problem are you trying to solve?
[EDIT] As of trailing comma: there's none, at least not any Oracle version I used (11g, 12c, 18cXE, 21cXE):
SQL> select listagg(id, ',') within group (order by null) result from test;
RESULT
------------------------------
1,2,3
SQL> select listagg(name, ',') within group (order by null) result from test;
RESULT
------------------------------
Alex,Amy,Jim
SQL>

concatenate column values from multiple rows in Oracle without duplicates

I can concatenate column values from multiple rows in Oracle using LISTAGG
But I want to avoid duplicates
Currently it return duplicates
select LISTAGG( t.id,',') WITHIN GROUP (ORDER BY t.id) from table t;
for example for data
ID
10
10
20
30
30
40
Returns 10,10,20,30,40,40
Instead 10,20,30,40
And I can't use distinct inside LISTAGG
select LISTAGG( distinct t.id,',') WITHIN GROUP (ORDER BY t.id) from table t;
Error
ORA-30482: DISTINCT option not allowed for this function
One option would be using regexp_replace():
select regexp_replace(
listagg( t.id,',') within group (order by t.id)
, '([^,]+)(,\1)+', '\1') as "Result"
from t
Demo
You can put the distinct in a subquery:
select LISTAGG( t.id,',') WITHIN GROUP (ORDER BY t.id) from (SELECT DISTINCT t.id FROM TABLE) t

Concatinate top 5 results in one column

I have a table that gives me the following output.
I want to write a query that gives me the result of the top 5 rows fetched from the above table (just col2) and then display them in just one column as comma separated.
Basically what I want the output as:
Can you give me the sql query for the same.
If your DB is MySQL, use:
select group_concat(col2 separator ', ') as str from myTable;
If your DB is Oracle, use:
select listagg(col2, ', ') within group (order by col1) as str from myTable;
If your DB is Postgres, use:
select string_agg(col2, ',' order by col1) as str from mytable;

TSQL get column names from dynamic query with formatting/conditions

I need to identify list of columns and its original value from dynamic SQL.
Example: I have this SQL statement:
#tsql = N'SELECT A.ID AS PROCESSID, COALESCE(STEP_ID,'''') AS programmid, NAME FROM DBO.TBL_LOG A'
As per this solution It will just return column name. I need both column name and its original value.
Expected result :
Can anyone please help with this? Thank you in advance.
Below code works for me temporary , If there will be too complex statement in select clause than it will not work.
;WITH CTE AS
(
SELECT NAME , SUBSTRING(LTRIM(#TSQL),7,CHARINDEX('FROM',LTRIM(#TSQL),0)-7) as QRY FROM sys.dm_exec_describe_first_result_set (#TSQL, null, 0)
)
,COLPOS as
(
select NAME,QRY, CHARINDEX(NAME ,QRY,LEN(QRY) - CHARINDEX(REVERSE(NAME),REVERSE(QRY),0)- LEN(NAME)) AS POS
FROM CTE
)
,POS AS (
SELECT NAME,QRY,POS,LAG(POS) OVER (order by (select 1)) LGPOS,LEAD(POS) OVER (order by (select 1)) LEADPOS
,LAG(NAME) OVER (order by (select 1)) LGNAME
FROM COLPOS
)
SELECT NAME , LTRIM(RTRIM(SUBSTRING (QRY,COALESCE(LGPOS+LEN(LGNAME),0),POS+LEN(NAME)-COALESCE(LGPOS+LEN(LGNAME),0)))) AS EXPRESSION
FROM POS

How to show query result in group? SQL Query

Right now my sql query display the result as follows.
though it is the correct result.
I prefer to have the have the result to show as follows.
How can I do this with SQL ? I am on SQL server 2008
I'm with the commenters, better to do this elsewhere, but it's simple enough in SQL using a CASE statement and the ROW_NUMBER() function:
;WITH cte AS (SELECT *,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY (SELECT 1)) RN
FROM YourTable)
SELECT CASE WHEN RN = 1 THEN CAST(ID AS VARCHAR(5)) ELSE '' END, Name
FROM cte
ORDER BY ID,RN
Demo: SQL Fiddle
This is not a job for SQL.
Any way, you can easily display it with comma separated values:
ID Names
1000 Honda, Toyota,...
1000 Honda, Toyota,...
SELECT ID, Names=
STUFF((SELECT ', ' + Name
FROM your_table b
WHERE b.ID= a.ID
FOR XML PATH('')), 1, 2, '')
FROM your_table a
GROUP BY ID