1

Ive been trying to use the GROUP function and also PIVOT but I cannot wrap my head around how to merge these tables and combine duplicate rows. Currently my SELECT statement returns results with duplicate UserID rows but I want to consolidate them into columns.

How would I join TABLE1 and TABLE2 into a new table which would look something like this:

NEW TABLE:
UserID    Username  ParentID 1   ParentID 2
--------- --------  --------     ----------
1         Dave      1             2
2         Sally     3             4



TABLE1:
UserID    Username  ParentID
--------- --------  --------
1         Dave      1
1         Dave      2
2         Sally     3
2         Sally     4


Table 2:
ParentID  Username
--------- --------
1         Sarah
2         Joe
3         Tom
4         Mark
Grantx
  • 315
  • 1
  • 10
  • 3
    You are looking for a recursive CTE. What RDBMS are you using (sql server, mysql, postgres, oracle, snowflake, teradata, mariadb, etc)? – JNevill Aug 23 '22 at 15:58
  • Hi. Sql developer edition 2019. I did think of using a cte but what is a recursive cte? – Grantx Aug 23 '22 at 17:01
  • Oracle. Not my specialty. I believe instead of recursive cte's oracle uses a `connect by` feature. [See here](https://stackoverflow.com/questions/50123407/simple-recursive-query-in-oracle) – JNevill Aug 23 '22 at 17:07

2 Answers2

1

This is mySql ver 5.6. Create a concatenated ParentID using group concat then separate the concatenated ParentID (1,2) and (3,4) into ParentID 1 and Parent ID 2.

SELECT t1.UserID, 
       t1.Username,
SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(t1.ParentID), ',', 1), ',', -1) AS `ParentID 1`,
SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(t1.ParentID), ',', 2), ',', -1) as `ParentID 2`
FROM TABLE1 t1
INNER JOIN TABLE2 t2 on t1.ParentID = t2.ParentID
GROUP BY t1.UserID
ORDER BY t1.UserID;


Result:
UserID  Username    ParentID 1  ParentID 2
1       Dave        1           2
2       Sally       3           4
jose_bacoy
  • 12,227
  • 1
  • 20
  • 38
1

O r a c l e
The with clause is here just to generate some sample data and, as such, it is not a part of the answer.
After joining the tables you can use LAST_VALUE analytic function with windowing clause to get the next PARENT_ID of the user. That column (PARENT_ID_2) contains a value only within the first row of a particular USER_ID (ROW_NUMBER analytic function). Afterwords just filter out rows where PARENT_ID_2 is empty...
Sample data:

WITH 
    tbl_1 AS
        (
            Select 1 "USER_ID", 'Dave' "USER_NAME", 1 "PARENT_ID" From Dual Union All
            Select 1 "USER_ID", 'Dave' "USER_NAME", 2 "PARENT_ID" From Dual Union All
            Select 2 "USER_ID", 'Sally' "USER_NAME", 3 "PARENT_ID" From Dual Union All
            Select 2 "USER_ID", 'Sally' "USER_NAME", 4 "PARENT_ID" From Dual 
        ),
    tbl_2 AS
        (
            Select  1 "PARENT_ID", 'Sarah' "USER_NAME" From Dual Union All
            Select  2 "PARENT_ID", 'Joe' "USER_NAME" From Dual Union All
            Select  3 "PARENT_ID", 'Tom' "USER_NAME" From Dual Union All
            Select  4 "PARENT_ID", 'Mark' "USER_NAME" From Dual 
        )

Main SQL:

SELECT 
    *
FROM  (
          SELECT  
                  t1.USER_ID "USER_ID", 
                  t1.USER_NAME "USER_NAME",
                  t1.PARENT_ID "PARENT_ID_1",
                  CASE  
                      WHEN ROW_NUMBER() OVER(PARTITION BY t1.USER_ID ORDER BY t1.USER_ID) = 1
                      THEN LAST_VALUE(t1.PARENT_ID) OVER(PARTITION BY t1.USER_ID ORDER BY t1.USER_ID ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING)
                  END "PARENT_ID_2"
          FROM 
              tbl_1 t1
          INNER JOIN 
              tbl_2 t2 ON(t1.PARENT_ID = t2.PARENT_ID)
      )
WHERE PARENT_ID_2 Is Not Null

... and the Result ...

--     USER_ID USER_NAME PARENT_ID_1 PARENT_ID_2
--  ---------- --------- ----------- -----------
--           1 Dave                1           2 
--           2 Sally               3           4

The windowing clause in this answer

ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING

takes curent and next row and returns the value defined by the analytic function (LAST_VALUE) taking care of grouping (PARTITION BY) and ordering of the rows. Regards...

d r
  • 3,848
  • 2
  • 4
  • 15