Tomasz N.

Tomasz N. Developer

Temat: Liczba przełożonych zliczenie

Witam,

Mam tabele zawierającą informacje o pracownikach i ich przełożonych,
Potrzebuję zliczyć ilu przełożonych ma nad sobą dana osoba.

Tabela zawiera dane np.:


UserId;Login;ManagerLogin
1;aaa;bbb;
2;bbb;ccc;
3;ccc;ddd
4;ddd;eee;
5;eee;fff;


Z danych wynika że np.: user o loginie = bbb ma 4 przełożonych ccc -> ddd -> eee -> fff

Prośba o pomoc w realizacji zapytania.

konto usunięte

Temat: Liczba przełożonych zliczenie

No to tak, jest sobie WITH RECURSIVE, które robi ładne zapytania rekurencyjne.

Na początek zróbmy sobie takie ładne coś:


WITH RECURSIVE data(login, manager_login, path) AS (
SELECT f.login, f.manager_login, ARRAY[f.login, f.manager_login]
FROM fun f
UNION ALL
SELECT f.login, f.manager_login, path || ARRAY[f.manager_login]
FROM fun f, data d
WHERE f.manager_login = d.login
)
SELECT * FROM data;


To zwraca takie dane:


login | manager_login | path
-------+---------------+---------------------------
aaa | bbb | {aaa,bbb}
bbb | ccc | {bbb,ccc}
ccc | ddd | {ccc,ddd}
ddd | eee | {ddd,eee}
eee | fff | {eee,fff}
aaa | bbb | {bbb,ccc,bbb}
bbb | ccc | {ccc,ddd,ccc}
ccc | ddd | {ddd,eee,ddd}
ddd | eee | {eee,fff,eee}
aaa | bbb | {ccc,ddd,ccc,bbb}
bbb | ccc | {ddd,eee,ddd,ccc}
ccc | ddd | {eee,fff,eee,ddd}
aaa | bbb | {ddd,eee,ddd,ccc,bbb}
bbb | ccc | {eee,fff,eee,ddd,ccc}
aaa | bbb | {eee,fff,eee,ddd,ccc,bbb}
(15 rows)


I teraz trzeba wybrać te najdłuższe. To najprościej zrobic za pomocą czegoś jak WINDOW FUNCTION.

Ale jeśli tylko interesująca jest ta liczba, to:


WITH RECURSIVE data(login, manager_login, path) AS (
SELECT f.login, f.manager_login, 1
FROM fun f
UNION ALL
SELECT f.login, f.manager_login, path + 1
FROM fun f, data d
WHERE f.manager_login = d.login
)
SELECT * FROM data;


Co daje:


login | manager_login | path
-------+---------------+------
aaa | bbb | 1
bbb | ccc | 1
ccc | ddd | 1
ddd | eee | 1
eee | fff | 1
aaa | bbb | 2
bbb | ccc | 2
ccc | ddd | 2
ddd | eee | 2
aaa | bbb | 3
bbb | ccc | 3
ccc | ddd | 3
aaa | bbb | 4
bbb | ccc | 4
aaa | bbb | 5
(15 rows)


No i teraz trzeba wziąć te największe liczby:


WITH RECURSIVE data(login, manager_login, path) AS (
SELECT f.login, f.manager_login, 1
FROM fun f
UNION ALL
SELECT f.login, f.manager_login, path + 1
FROM fun f, data d
WHERE f.manager_login = d.login
)
SELECT login, max(path)
FROM data
GROUP BY login
ORDER BY login;


I mamy:


login | max
-------+-----
aaa | 0
bbb | 1
ccc | 2
ddd | 3
eee | 4
(5 rows)


A zaten dla loginu 'bbb' wystarczy dać to:


WITH RECURSIVE data(login, manager_login, path) AS (
SELECT f.login, f.manager_login, 1
FROM fun f
UNION ALL
SELECT f.login, f.manager_login, path + 1
FROM fun f, data d
WHERE f.manager_login = d.login
)
SELECT login, max(path)
FROM data
WHERE login = 'bbb'
GROUP BY login;


I mamy:


szymon=# \e
login | max
-------+-----
bbb | 4
(1 row)



Aha i mała uwaga: to nie ma zabezpieczenia przed cyklami, wiec jak cykl będzie, to krowy przestaną mleko dawać, a sąsiadowi zepsują rower.Ten post został edytowany przez Autora dnia 11.04.17 o godzinie 21:19



Wyślij zaproszenie do