Oracle concatenation of columns with comma [duplicate] - sql

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can I combine multiple rows into a comma-delimited list in Oracle?
Could some one please tell me how to achieve the following?
Table:
efforts_id cycle_name release_name
123 quarter march
123 half april
123 full april
124 quarter may
My expected output:
efforts_id cycle_name release_name
123 quarter,half,full march,april
124 quarter may
I am a beginner in oracle so not sure how to do this. Any help would be appreciated.
Thanks

What you need is "string aggregation". Tim Hall's excellent site shows the alternatives you have depending on the exact version of Oracle you have: http://www.oracle-base.com/articles/misc/string-aggregation-techniques.php
In 11gR2 (current at time of writing), you should use the listagg function:
select
efforts_id,
listagg(cycle_name, ',') within group (order by cycle_name) as cycle_name,
listagg(release_name, ',') within group (order by release_name) as release_name
from my_table
group by efforts_id;
Note that the use of the wm_concat function is unsupported by Oracle...

You will want to use LISTAGG() to perform this task. The other answers don't remove any of the duplicate values, to remove the duplicates, you can use something similar to this:
select c.efforts_id,
c.cycle_name,
listagg(r.release_name, ', ') within group (order by c.efforts_id) as release_name
from
(
select efforts_id,
listagg(cycle_name, ', ') within group (order by efforts_id) as cycle_name
from yourtable
group by efforts_id
) c
inner join
(
select distinct efforts_id, release_name
from yourtable
) r
on c.efforts_id = r.efforts_id
group by c.efforts_id, c.cycle_name
See SQL Fiddle with Demo

If you have Oracle 11g R2, then LISTAGG is the preferred way to do it:
SELECT efforts_id,
LISTAGG(cycle_name) WITHIN GROUP(ORDER BY cycle_name),
LISTAGG(release_name) WITHIN GROUP(ORDER BY cycle_name)
FROM MY_TABLE
GROUP BY efforts_id
If not, this article shows the alternative ways of doing it.

Through the WM_concat function (and GROUP BY of course)
SELECT efforts_id, wm_concat(cycle_name), wm_concat(release_name)
FROM MY_TABLE
GROUP BY efforts_id
Hmmm, just found this:
Note that WM_CONCAT is undocumented and unsupported by Oracle, meaning it should not be used in production systems
The LISTAGG function, which can produce the same output as WM_CONCAT is both documented and supported by Oracle.

Related

PERCENTILE_DISC - Exclude Nulls

I'm having trouble with PERCENTILE_DISC where the below query is returning the "Median" as 310, but the actual Median is 365. It's returning 310 as it's including the NULL value.
Is there a way to have PERCENTILE_DISC exclude NULLS? Gordon Lindoff mentioned in this post that NULLs are excluded from PERCENTILE_DISC but this doesn't seem to be the case.
Here's the simple example showing the problem:
SELECT
DISTINCT PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY Numbers) OVER (PARTITION BY Category)
from
(
select 1 as Category,420 as Numbers
union all
select 1,425
union all
select 1,NULL
union all
select 1,310
union all
select 1,300
) t1
According to the documentation for PERCENTILE_DISC, the result is always equal to a specific column value.
PERCENTILE_DISC does ignore the NULL-s: if you ask for PERCENTILE_DISC(0) you would get 300, not NULL.
To get the value you want (365, which is the average between 310 and 420), you need to use PERCENTILE_CONT. See the first example in the documentation mentioned above, where it highlights the difference between PERCENTILE_CONT and PERCENTILE_DISC.

How to use LIST_AGG in netsuite

I want to concatenate the result of a column in Netsuite. I tried List_Agg but no luck.
select t.id, LIST_AGG(tn.trackingnumber, ',')
from transaction t
left join trackingnumber tn on
(
INSTR(', '||t.trackingnumberlist||', ', ', '||tn.id||', ') > 0
)
where t.id = 1
Here t.trackingnumberlist = 1,2,3
Any suggestion/alternate of LIST_AGG
I've spoken with NetSuite support about this in the past, and unfortunately, it is not possible. Their ODBC SuiteAnalytics Connect service is based on the SQL-92 standard, rather than any Oracle database standard, thus it does not have this feature, as LIST_AGG was added to Oracle SQL back in 11g in 2007 (14 years ago - https://oracle-base.com/articles/misc/string-aggregation-techniques#listagg).
I've had to resort to performing my own aggregate functions within my C# code after pulling the data over, as SQL-92 is so limited, that it's not possible to even reproduce the function of what LIST_AGG does in that environment.
Sorry to be the bearer of bad news.
I'm not sure about SuiteAnalytics Connect, but I can run the following query in SuiteScript using the N/query.runSuiteQL() function. This is in Netsuite 2022.1.
SELECT
LISTAGG (tranid, ',') WITHIN GROUP(ORDER BY tranid) AS document_numbers,
trandate AS date
FROM
transaction
WHERE
rownum < 10
GROUP BY trandate
It does appear that there is a character limit for each result, so if you are seeing errors, you might try reducing the number of results you are aggregating.

What is missing (if anything) from this SQL statement? [duplicate]

This question already has an answer here:
Mysql : Aggregation function is not working without group by
(1 answer)
Closed 1 year ago.
SELECT EXTRACT(YEAR FROM created_at) AS yr, count(*) AS users_count
FROM users;
I'm new to SQL (so new that I can't find anything wrong with this). There may not be, and it may be a trick question. Would appreciate feedback!
You should use "Group BY" function too, because you use COUNT function with an another column.
For example:
SELECT EXTRACT(YEAR FROM created_at) AS yr, count(*) AS users_count FROM users group by YR;

converting oracle's listagg to postgres

I am trying to convert some Oracle queries to Postgres and came across listagg.
Oracle code
select max(eta) eta, mso_id, listagg(carrier_name, ',')
within group (order by eta) as carrier
from tb_flight_schedule group by mso_id;
I found out that Postgres's equivalent of listagg is string_agg and proceeded to swap the listagg with string_agg. However, I am encountering error (ERROR: function string_agg(character varying, unknown, date) does not exist). Am I missing something in the query? Postgres query is below:
select max(eta) eta, mso_id, string_agg(carrier_name, ',')
WITHIN GROUP (ORDER BY eta) as carrier
from tb_flight_schedule group by mso_id;
In Postgres, the within group clause is only used for orderd-set aggregate functions - i.e., functions that require an order by clause (e.g., the percentile functions). An optional order by clause, such as string_agg's, goes inside the function's arguments:
SELECT MAX(eta) eta, mso_id, STRING_AGG(carrier_name, ',' ORDER BY eta) AS carrier
FROM tb_flight_schedule
GROUP BY mso_id;

SQL convert from 3 to 2 columns

I am trying to convert 3 columns into 2. Is there a way I can do this with the example below or a different way?
For example.
Year Temp Temp1
2015 5 6
Into:
Year Value
Base 5
2015 6
This is called unpivot, pivot is the exact opposite(make 2 columns into more) .
You can do this with a simple UNION ALL:
SELECT 'Base',s.temp FROM YourTable s
UNION ALL
SELECT t.year,t.temp1 FROM YourTable t
This relays on what you wrote on the comments, if year is constant , you can replace it with '2015'
You could use CROSS APPLY and row constructor:
SELECT s.*
FROM t
CROSS APPLY(VALUES('Base', Temp),(CAST(Year AS NVARCHAR(100)), Temp1)
) AS s(year,value);
LiveDemo
There is more than one answer to your question. Using UNION ALL seems to be the most simple solution.
I suggest reading this thread Converting Columns into rows with their respective data in sql server, as it provides a lot more details, and you can try and test how different solutions will work for you.