Reb32
Reb32

Reputation: 17

How to output data on one line per ID in Oracle SQL?

This works to get me all the data I need, but outputs a separate row for each side of the UNION when what I really want is to get all parent contacts on the same row as the student ID. That is, I want a row with a.id and then all the info for contact_1, contact_2, contact_3 and contact_4 in the same row. I'm guessing UNION was the wrong choice...

SELECT final.* 
    FROM (
        SELECT 
        --Name 1 in P1 household
        a.id
        ,a.name1_web_user_id as contact_1_id
        ,a.name1_full_name as contact_1_name
        ,case 'Name1:Mobile' 
            when Other_No_Type_1 then Other_No_1
            when Other_No_Type_2 then Other_No_2
            when Other_No_Type_3 then Other_No_3
            when Other_No_Type_4 then Other_No_4
            end as contact_1_mobile
        ,a.email as contact_1_email
       
        --Name 2 in P1 household
        ,a.name2_web_user_id as contact_2_id
        ,a.name2_full_name as contact_2_name
        ,case 'Name2:Mobile' 
            when Other_No_Type_1 then Other_No_1
            when Other_No_Type_2 then Other_No_2
            when Other_No_Type_3 then Other_No_3
            when Other_No_Type_4 then Other_No_4
            end as contact_2_mobile
        ,a.EMAIL_2 as contact_2_email
            
    FROM rg_student s left outer join rg_addr a on s.id = a.id
                WHERE  (
                (a.addr_code='P1' AND a.rg_active = 'Y') AND ((a.name1_web_user_id is not null) OR (a.name2_web_user_id is not null))
                            AND a.id in(SELECT id from rg_student where student_group='Student')
                        )
    UNION
    
        SELECT 
        --Name 1 in P2 household
        a.id
        ,a.name1_web_user_id as contact_3_id
        ,a.name1_full_name as contact_3_name
        ,case 'Name1:Mobile' 
            when Other_No_Type_1 then Other_No_1
            when Other_No_Type_2 then Other_No_2
            when Other_No_Type_3 then Other_No_3
            when Other_No_Type_4 then Other_No_4
            end as contact_3_mobile
        ,a.email as contact_3_email
        
        --Name 2 in P2 household
        ,a.name2_web_user_id as contact_4_id
        ,a.name2_full_name as contact_4_name
        ,case 'Name2:Mobile' 
            when Other_No_Type_1 then Other_No_1
            when Other_No_Type_2 then Other_No_2
            when Other_No_Type_3 then Other_No_3
            when Other_No_Type_4 then Other_No_4
            end as contact_4_mobile
        ,a.EMAIL_2 as contact_4_email
            
    FROM rg_student s left outer join rg_addr a on s.id = a.id
                WHERE  (
                        (a.addr_code='P2' AND a.rg_active = 'Y') AND ((a.name1_web_user_id is not null) OR (a.name2_web_user_id is not null))
                            AND a.id in(SELECT id from rg_student where student_group='Student')
                        )                
        )final
    ORDER BY final.id

I've tried to replace the UNION with JOIN, as guided, and simplified the select as follows, but now get error about FROM being in the wrong place.


        SELECT 
        --Name 1 in P1 household
        s.id
        ,a.name1_web_user_id as contact_1_id
        ,a.name1_full_name as contact_1_name
        ,case 'Name1:Mobile' 
            when a.Other_No_Type_1 then Other_No_1
            when a.Other_No_Type_2 then Other_No_2
            when a.Other_No_Type_3 then Other_No_3
            when a.Other_No_Type_4 then Other_No_4
            end as contact_1_mobile
        ,a.email as contact_1_email
       
        --Name 2 in P1 household
        ,a.name2_web_user_id as contact_2_id
        ,a.name2_full_name as contact_2_name
        ,case 'Name2:Mobile' 
            when a.Other_No_Type_1 then Other_No_1
            when a.Other_No_Type_2 then Other_No_2
            when a.Other_No_Type_3 then Other_No_3
            when a.Other_No_Type_4 then Other_No_4
            end as contact_2_mobile
        ,a.email_2 as contact_2_email
            
        --Name 1 in P2 household
        s.id
        ,b.name1_web_user_id as contact_3_id
        ,b.name1_full_name as contact_3_name
        ,case 'Name1:Mobile' 
            when b.Other_No_Type_1 then Other_No_1
            when b.Other_No_Type_2 then Other_No_2
            when b.Other_No_Type_3 then Other_No_3
            when b.Other_No_Type_4 then Other_No_4
            end as contact_3_mobile
        ,b.email as contact_3_email
        
        --Name 2 in P2 household
        ,b.name2_web_user_id as contact_4_id
        ,b.name2_full_name as contact_4_name
        ,case 'Name2:Mobile' 
            when b.Other_No_Type_1 then Other_No_1
            when b.Other_No_Type_2 then Other_No_2
            when b.Other_No_Type_3 then Other_No_3
            when b.Other_No_Type_4 then Other_No_4
            end as contact_4_mobile
        ,b.email_2 as contact_4_email
            
    FROM rg_student s
        left outer join rg_addr a on s.id=a.id
        WHERE  ((a.addr_code='P1' AND a.rg_active = 'Y') 
                AND s.id in(SELECT id from rg_student where student_group='Student'))
        left outer join rg_addr b on s.id=b.id
        WHERE  ((a.addr_code='P2' AND b.rg_active = 'Y') 
                 AND s.id in(SELECT id from rg_student where student_group='Student'))

This now gives me the single row per student that I need, but also disregards my need to (SELECT id from rg_student where student_group='Student') in the FROM, so it's now returning all students in any group (incl. withdrawn, graduate, etc.). I hear that I can't use WHERE in the FROM, but not sure how to define the student_group I need.

       SELECT DISTINCT
       --Name 1 in P1 household
       s.id
       ,a.name1_web_user_id as contact_1_id
       ,a.name1_full_name as contact_1_name
       ,case 'Name1:Mobile' 
           when a.Other_No_Type_1 then a.Other_No_1
           when a.Other_No_Type_2 then a.Other_No_2
           when a.Other_No_Type_3 then a.Other_No_3
           when a.Other_No_Type_4 then a.Other_No_4
           end as contact_1_mobile
       ,a.email as contact_1_email
      
       --Name 2 in P1 household
       ,a.name2_web_user_id as contact_2_id
       ,a.name2_full_name as contact_2_name
       ,case 'Name2:Mobile' 
           when a.Other_No_Type_1 then a.Other_No_1
           when a.Other_No_Type_2 then a.Other_No_2
           when a.Other_No_Type_3 then a.Other_No_3
           when a.Other_No_Type_4 then a.Other_No_4
           end as contact_2_mobile
       ,a.email_2 as contact_2_email
           
       --Name 1 in P2 household
       ,s.id
       ,b.name1_web_user_id as contact_3_id
       ,b.name1_full_name as contact_3_name
       ,case 'Name1:Mobile' 
           when b.Other_No_Type_1 then b.Other_No_1
           when b.Other_No_Type_2 then b.Other_No_2
           when b.Other_No_Type_3 then b.Other_No_3
           when b.Other_No_Type_4 then b.Other_No_4
           end as contact_3_mobile
       ,b.email as contact_3_email
       
       --Name 2 in P2 household
       ,b.name2_web_user_id as contact_4_id
       ,b.name2_full_name as contact_4_name
       ,case 'Name2:Mobile' 
           when b.Other_No_Type_1 then b.Other_No_1
           when b.Other_No_Type_2 then b.Other_No_2
           when b.Other_No_Type_3 then b.Other_No_3
           when b.Other_No_Type_4 then b.Other_No_4
           end as contact_4_mobile
       ,b.email_2 as contact_4_email
           
   FROM rg_student s
       left outer join rg_addr a on s.id=a.id
       AND  a.addr_code='P1' AND a.rg_active = 'Y' 
       AND s.id in(SELECT id from rg_student where student_group='Student')
           left outer join rg_addr b on s.id=b.id
           AND  a.addr_code='P2' AND b.rg_active = 'Y' 
           AND s.id in(SELECT id from rg_student where student_group='Student')

Upvotes: 0

Views: 155

Answers (1)

Junjie
Junjie

Reputation: 521

Yes, union creates other rows for each student's id.

To put all the contact info on one row per id, you have to join your rg_addr to rg_student twice, with the difference in the condition for addr_code, like so:

select s.id,
  a.name1_web_user_id contact_1_id,
  a.name1_full_name contact_1_name,
  a.email contact_1_email,
  ... --other info of name 1 in P1 household
  a.name2_web_user_id contact_2_id,
  a.name2_full_name contact_2_name,
  a.email_2 contact_2_email,
  ... --other info of name 2 in P1 household
  b.name1_web_user_id contact_3_id,
  b.name1_full_name contact_3_name,
  b.email contact_3_email,
  ... --other info of name 1 in P2 household
  b.email_2 contact_4_email,
  b.name2_web_user_id contact_4_id,
  b.email_2 contact_4_email,
  ... --other info of name 2 in P2 household
from rg_student s
  left outer join rg_addr a on s.id=a.id
    and a.addr_code='P1' and a.rg_active='Y'
    and ... --and other required conditions
  left outer join rg_addr b on s.id=b.id
    and a.addr_code='P2' and b.rg_active='Y'
    and ... --and other required conditions

Note that what I put for id is s prefix instead of a to make sure there's a student ID in case the student does not have corresponding rg_addr record.


Edit: Additional code changes for student group requirement:

...
FROM rg_student s
  left outer join rg_addr a on s.id=a.id
    AND  a.addr_code='P1' AND a.rg_active = 'Y' 
    --AND s.id in(SELECT id from rg_student where student_group='Student')
  left outer join rg_addr b on s.id=b.id
    AND  a.addr_code='P2' AND b.rg_active = 'Y' 
    --AND s.id in(SELECT id from rg_student where student_group='Student')
WHERE s.student_group='Student'

Upvotes: 0

Related Questions