Skip to content
Advertisement

Finding couples of occurrences – Postgresql

I need to find possible couplings of employees and department that they worked for. I need to include only the couplings of 2 different departments, so if an employee worked for more than 2 departments, I need to divide them into couplings of 2 departments to show the transfers. Also the period of the contract of the employee at the first department must be earlier than the contract at the second department. I need to list the values as “first_name”, “last_name, “deptnr1”, “dept1”, “deptnr2”, “dept2”.

For example John Doe worked for department A(deptnr 9) from 01/01/2016 to 06/06/2016 and for department B(deptnr 3) from 10/06/2016 to 12/12/2017, the result should be like :

John, Doe, 9, A, 3, B

If he then returned to his job at department A, there should be another coupling like this to make his 2nd transfer visible:

John, Doe, 3, B, 9, A

so if he transfers around, we should have as many couplings of departments as possible, in this case 2 transfers, thus 2 couplings out of 3 departments(A => B => A so A,B/B,A).

I have 4 tables.

Person (PK email, first_name, last_name, FK postcode, FK place_name)

Employee(PK employeenr, FK email)

Department(PK departmentnr, name, FK postcode, FK place_name)

Contract(PK periode_begin, PK periode_end, FK departmentnr, FK employeenr)

I have tried this but I don’t know how to make use of aliases to take values from let’s say department.name and put them on other columns as name1 and name2. Also I couldn’t figure out a way to make couplings out of let’s say four transfers like (A=> B=> C=> D=> E TO A,B/B,C/C,D/D,E).

SELECT
    first_name, 
    last_name, 
    d1.departmentnr AS deptnr1, 
    d1.name AS dept1,
    d2.departmentnr AS deptnr2, 
    d2.name AS dept2,
FROM person
INNER JOIN employee ON employee.email=person.email
INNER JOIN contract ON contract.employeenr = employee.employeenr
INNER JOIN department d1 ON department.departmentnr = contract.departmentnr
where contract.employeenr in 
(SELECT employeenr FROM contract 
GROUP BY employeenr HAVING COUNT(employeenr)>1 
AND COUNT(employeenr)>1)

Advertisement

Answer

Use the window function lead()

select
    first_name,
    last_name,
    deptnr1,
    dept1,
    deptnr2,
    dept2
from (
    select
        first_name,
        last_name,
        departmentnr as deptnr1,
        name as dept1,
        lead(departmentnr) over w as deptnr2,
        lead(name) over w as dept2,
        periode_begin
    from person p
    join employee e using(email)
    join contract c using(employeenr)
    join department d using(departmentnr)
    window w as (partition by email order by periode_begin)
    ) s
where deptnr2 is not null
order by first_name, last_name, periode_begin

Read also about window functions in the documentation.

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement