Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Concat row values if they match?

I have a table:

ID Text
1 A1 Text – words
2 A1 Text – wordsa
3 B1 Sentence – sentence
4 B1 Sentence – sentence b

What I’m trying to achieve:

ID Text
1 A1 Text – words, A1 Text – wordsa
2 B1 Sentence – sentence, B1 Sentence – sentence b

I’m not sure how to approach this or is there a function that would deal with this? I need at least a suggestion to get started.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

EDIT – I updated the table slighty. As ofcourse I don’t want to aggregate the entire table into 1 row, hopefully the tables show what I’m trying to say more clearly.

>Solution :

Option 1:

If you want to find chains of successive rows with where the start of the string matches the next string then you can use a hierarchical function and collate the rows using SYS_CONNECT_BY_PATH:

SELECT CONNECT_BY_ROOT id AS id,
       SUBSTR(
         SYS_CONNECT_BY_PATH(Text, ', '),
         3
       ) AS Text
FROM   table_name
WHERE  CONNECT_BY_ISLEAF = 1
START WITH
       id IN (SELECT id
              FROM   table_name
              WHERE  CONNECT_BY_ISLEAF = 1
              AND    LEVEL = 1
              CONNECT BY NOCYCLE
                     PRIOR text LIKE text || '%'
             )
CONNECT BY NOCYCLE
       text LIKE PRIOR text || '%';

Which, for the sample data:

CREATE TABLE table_name (ID, Text) AS
SELECT 1, 'A1 Text - words' FROM DUAL UNION ALL
SELECT 2, 'A1 Text - wordsa' FROM DUAL UNION ALL
SELECT 3, 'B1 Sentence - sentence' FROM DUAL UNION ALL
SELECT 4, 'B1 Sentence - sentence b' FROM DUAL;

Outputs:

ID TEXT
1 A1 Text – words, A1 Text – wordsa
3 B1 Sentence – sentence, B1 Sentence – sentence b

Option 2:

From Oracle 12, if you want to find the first string and then all the strings that also start with that first string then you can use MATCH_RECOGNIZE:

SELECT MIN(first_id) AS id,
       LISTAGG(text, ',') WITHIN GROUP (ORDER BY text) AS text
FROM   table_name
MATCH_RECOGNIZE(
  ORDER BY text
  MEASURES
    FIRST(id) AS first_id,
    MATCH_NUMBER() AS mno
  ALL ROWS PER MATCH
  PATTERN (matches+)
  DEFINE matches AS (text LIKE FIRST(text) || '%')
)
GROUP BY mno

Which, for the sample data, gives the same output (but may give a different output if there was more data as Option 1 is finding individual paths through the hierarchy and Option 2 is finding all children that match an ancestor).

In earlier versions, you should get the equivalent result using:

SELECT root_id AS id,
       LISTAGG(text, ', ') WITHIN GROUP (ORDER BY ROWNUM) AS text
FROM   (
  SELECT DISTINCT
         CONNECT_BY_ROOT id AS root_id,
         id,
         text
  FROM   table_name
  START WITH
         id IN (SELECT id
                FROM   table_name
                WHERE  CONNECT_BY_ISLEAF = 1
                AND    LEVEL = 1
                CONNECT BY NOCYCLE
                       PRIOR text LIKE text || '%'
               )
  CONNECT BY NOCYCLE
         text LIKE PRIOR text || '%'
  ORDER SIBLINGS BY text
)
GROUP BY root_id

db<>fiddle here

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading