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