Home > Blockchain >  Aggregate values to separate columns from using WM_CONCAT
Aggregate values to separate columns from using WM_CONCAT

Time:07-13

I have these tables and values:

Table1:

AppID Desc
1 Sample

Table2:

AddID AppID Address
1 1 Add1
2 1 Add2
3 1 Add3
4 1 Add4

With my current code:

SELECT app.AppID
       add.Address as Addresses

FROM Table1 app
LEFT JOIN   (SELECT     AppID,
                        REPLACE(WM_CONCAT(Address), ',', '; ') AS Address
            
            FROM Table2
            GROUP BY AppID) add ON app.AppID = add.AppID

ORDER BY app.AppID;

I get this output:

AppID Addresses
1 Add1; Add2; Add3; Add4

But how can I possibly have this output instead?:

  1. Put the addresses in separate columns instead of being joined in one column
  2. Only limit the column for address to only 3.

DESIRED OUTPUT:

AppID Address1 Address2 Address3
1 Add1 Add2 Add3

I am using Oracle Developer v3.2.10

CodePudding user response:

For such an output, you don't even need table1 as all columns are already contained in table2. If you apply conditional aggregation, you get the result.

Sample data:

SQL> with
  2  table1 (appid, description) as
  3    (select 1, 'Sample' from dual),
  4  table2 (addid, appid, address) as
  5    (select 1, 1, 'Add1' from dual union all
  6     select 2, 1, 'Add2' from dual union all
  7     select 3, 1, 'Add3' from dual union all
  8     select 4, 1, 'Add4' from dual
  9    )

Query:

 10  select b.appid,
 11    max(case when b.addid = 1 then address end) address1,
 12    max(case when b.addid = 2 then address end) address2,
 13    max(case when b.addid = 3 then address end) address3
 14  from table2 b
 15  group by b.appid;

     APPID ADDRESS1   ADDRESS2   ADDRESS3
---------- ---------- ---------- ----------
         1 Add1       Add2       Add3

SQL>

Also, forget that wm_concat exists. It is undocumented function and - although it works in certain database versions - once you upgrade to 12c (or higher), your code won't work any more because Oracle removed wm_concat. Switch to something else (listagg if possible, xmlagg otherwise).

CodePudding user response:

Do not use WM_CONCAT. It is an undocumented function that was removed in Oracle 12 and no longer exists.

Number the rows using the ROW_NUMBER analytic function and then PIVOT:

SELECT *
FROM   (
  SELECT t1.AppID,
         Address,
         ROW_NUMBER() OVER (PARTITION BY t1.AppID ORDER BY t2.AddID) AS rn
  FROM   table1 t1
         LEFT OUTER JOIN table2 t2
         ON (t1.appid = t2.appid)
)
PIVOT (
  MAX(Address) FOR rn IN (
    1 AS address1,
    2 AS address2,
    3 AS address3
  )
);

Or, number the rows and then use conditional aggregation:

SELECT appid,
       MAX(CASE rn WHEN 1 THEN address END) AS address1,
       MAX(CASE rn WHEN 2 THEN address END) AS address2,
       MAX(CASE rn WHEN 3 THEN address END) AS address3
FROM   (
  SELECT t1.AppID,
         Address,
         ROW_NUMBER() OVER (PARTITION BY t1.AppID ORDER BY t2.AddID) AS rn
  FROM   table1 t1
         LEFT OUTER JOIN table2 t2
         ON (t1.appid = t2.appid)
)
GROUP BY appid

Which, for the sample data:

CREATE TABLE table1 (AppID PRIMARY KEY, "DESC") AS
SELECT 1, 'Sample' FROM DUAL;

CREATE TABLE table2 (AddID PRIMARY KEY, AppID, Address) AS
SELECT 1, 1, 'Add1' FROM DUAL UNION ALL
SELECT 2, 1, 'Add2' FROM DUAL UNION ALL
SELECT 3, 1, 'Add3' FROM DUAL UNION ALL
SELECT 4, 1, 'Add4' FROM DUAL;

Both output:

APPID ADDRESS1 ADDRESS2 ADDRESS3
1 Add1 Add2 Add3

db<>fiddle here

  • Related