Saya memiliki dua tabel Employee, Employeerows. Saya harus menarik catatan karyawan yang memiliki peran 2 atau 3. Saya memiliki pertanyaan di bawah ini.

SELECT
    E.ID,
    E.NAME,
    ER.PHONE,
    ER.ADDRESS,
    ER.ROLE
    
FROM
 EMPLOYEE E LEFT JOIN EMPLOYEEROWS ER ON E.ID = ER.ID WHERE ER.ROLE_ID IN (2,3)

Ini mengembalikan 1 atau 2 catatan untuk setiap karyawan

ID      NAME        PHONE       ADDRESS     ROLE
1       ABC         9898989     ABC NJ       2
1       ABC         7878787     ABC XJ       3
2       DEF         7898765     DEF NJ       2

Tetapi saya harus menggabungkan dua catatan menjadi satu untuk karyawan itu dengan nomor telepon dan alamat sebagai kolom terpisah jika karyawan tersebut memiliki 2 catatan. Hasil saya seharusnya seperti ini.

ID      NAME        PHONE       ALT_PHONE     ADDRESS      ALT_ADDESS   
1       ABC         9898989     7878787        ABC NJ       ABC XJ          
2       DEF         7898765                    DEF NJ

Tolong bantu saya dengan ini.

0
Pradeep Charan 21 Desember 2020, 14:06

3 jawaban

Jawaban Terbaik

Anda dapat menggunakan agregasi bersyarat. Tapi left join tampaknya berlebihan. Anda hanya ingin menggunakan left join jika Anda ingin "karyawan" yang tidak memiliki baris.

Ini tampak dari data Anda bahwa "2" sesuai dengan alamat utama dan "3" ke alternatif:

select e.id, e.name,
       max(case when er.role_id = 2 then er.phone end) as phone,
       max(case when er.role_id = 3 then er.phone end) as alt_phone,
       max(case when er.role_id = 2 then er.address end) as address,
       max(case when er.role_id = 3 then er.address end) as alt_address
from employee e join
     employeerows er
     on e.id = er.id
where er.role_id in (2, 3)
group by e.id, e.name;

Namun, jika "2" bisa hilang, maka Anda akan mengucapkan ini sebagai:

select e.id, e.name,
       max(case when seqnum = 2 then er.phone end) as phone,
       max(case when seqnum = 3 then er.phone end) as alt_phone,
       max(case when seqnum = 2 then er.address end) as address,
       max(case when seqnum = 3 then er.address end) as alt_address
from employee e join
     (select er.*,
             row_number() over (partition by er.id order by er.role_id) as seqnum
      from employeerows er
      where er.role_id in (2, 3)
     ) er
     on e.id = er.id
group by e.id, e.name;
2
Gordon Linoff 21 Desember 2020, 12:02

Anda dapat berporos dengan agregasi bersyarat:

select e.id, e.name,
    max(case when er.role_id = 2 then er.phone   end) as phone,
    max(case when er.role_id = 3 then er.phone   end) as alt_phone,
    max(case when er.role_id = 2 then er.address end) as address,
    max(case when er.role_id = 3 then er.address end) as alt_address
from employee e 
left join employeerows er on e.id = er.id where er.role_id in (2,3)
group by e.id, e.name
1
GMB 21 Desember 2020, 11:12

Anda dapat menggunakan agregasi bersyarat. Tetapi kueri Anda tidak melakukan LEFT OUTER JOIN tetapi INNER JOIN karena Anda telah menggunakan er.role_id in (2,3) dalam klausa WHERE.

Gunakan teknik agregasi berikut untuk mendapatkan hasil yang diinginkan:

SELECT
    E.ID,
    E.NAME,
    MIN(ER.PHONE),
    CASE WHEN MIN(ER.PHONE) <> MAX(ER.PHONE) THEN MAX(ER.PHONE) END AS ALT_PHONE,
    MIN(ER.ADDRESS),
    CASE WHEN MIN(ER.ADDRESS) <> MAX(ER.ADDRESS) THEN MAX(ER.ADDRESS) END AS ALT_ADDRESS
FROM EMPLOYEE E 
LEFT JOIN EMPLOYEEROWS ER ON E.ID = ER.ID 
                   AND ER.ROLE_ID IN (2,3) -- added it in the join condition
GROUP BY E.ID, E.NAME;
1
Popeye 21 Desember 2020, 11:26