Das Diagramm wurde verwendet, um die Unterordnung zwischen Mitarbeitern anstelle der zuvor in der Abteilungstabelle verwendeten Vorfahren-Kind-Methode zu implementieren.
Die Erfahrung hat sich als erfolgreich erwiesen, vielleicht ist sie für jemanden nützlich und hilft, Zeit zu sparen. Einmal suchte ich nach einer Implementierung in pqSQL, aber anscheinend sah ich schlecht aus. Ich musste es selbst implementieren. Was im Allgemeinen sogar das Beste ist, die Aufgabe ist interessant, es ist immer schön, etwas mit eigenen Händen zu tun, damit die Zeit nicht verschwendet wird.
Eingabedaten
Im Allgemeinen gibt es eine Standardtabelle "Mitarbeiterposition" mit der Primärschlüssel- ID . Positionen haben eine Hierarchie der Unterordnung "Chefangestellter". Die Idee ist, dass die Verknüpfungen zwischen Posts in einem separaten Entitätsdiagramm gespeichert werden .
Um einen Pfad in der Grafik zu finden, wurde der Dijkstra-Algorithmus verwendet. Eine allgemeine Beschreibung finden Sie beispielsweise hier
Ausgabe
- Liste der nachgeordneten Mitarbeiter hierfür
- Liste der Chefs für diesen Mitarbeiter
- Ist der Mitarbeiter dafür ein Untergebener?
- Liste der dafür untergeordneten Mitarbeiter (Weg vom Chef zum Mitarbeiter)
Implementierung mit PL / pgSQL
Speichern eines Diagramms als Randtabelle
Die Eckpunkte sind die ID- Werte der Zieltabelle.
CREATE TABLE graph
(
vertex integer NOT NULL , --id
edge integer NOT NULL , --id
vertex_order integer NOT NULL -- ( 0 , 1 )
);
Verwenden Sie die Sequenz, um die ID der Kante zu generieren
CREATE SEQUENCE enge_seq OWNED BY graph.edge;
Randtabelle füllen
Zwei INSERT-Operationen werden verwendet , um eine neue Kante einzufügen (Eckpunkte id0, id1 ).
-- id
new_id = nextval('enge_seq');
--
INSERT INTO graph (vertex , edge , vertex_order ) VALUES ( id0 , new_id , 0 );
--
INSERT INTO graph (vertex , edge , vertex_order ) VALUES ( id1 , new_id , 1 );
Abrufen einer Liste untergeordneter Mitarbeiter für eine bestimmte current_id
SELECT
id
FROM
graph
WHERE
vertex_order = 1 AND
edge IN (SELECT edge FROM graph WHERE vertex = current_id AND vertex_order = 0 );
Abrufen der Liste der Bosse für eine bestimmte current_id
SELECT
id
FROM
graph
WHERE
vertex_order = 0 AND
edge IN (SELECT edge FROM graph WHERE vertex = current_id AND vertex_order = 1 );
Erzeugung einer Verfügbarkeitsmatrix (Dijkstra-Algorithmus) aus einem gegebenen Scheitelpunkt start_id
Erstellen einer temporären Tabelle tmp_matrix
CREATE TEMPORARY TABLE tmp_matrix
AS
(
SELECT
DISTINCT vertex ,
FALSE AS label ,
999999 AS distance ,
FALSE AS is_finish
FROM
graph
);
Anfangspopulation der Tabelle tmp_matrix
UPDATE tmp_matrix
SET label = TRUE , distance = 0
WHERE vertex = current_id ;
current_id = start_id ;
SELECT
distance
INTO
current_distance
FROM
tmp_matrix
WHERE
vertex = current_id;
SELECT
EXISTS (SELECT 1 FROM tmp_matrix WHERE label = FALSE )
INTO
not_visit;
Ausfüllen der Verfügbarkeitsmatrix
WHILE not_visit
LOOP
FOR v_rec IN
SELECT
*
FROM
tmp_matrix
WHERE
NOT label AND
--
vertex IN ( SELECT
id
FROM
graph
WHERE
vertex_order = 1 AND
edge IN (SELECT
edge
FROM
graph
WHERE
vertex = current_id AND vertex_order = 0 ))
LOOP
--
IF v_rec.distance > (current_distance +1)
THEN
UPDATE tmp_matrix SET distance = (current_distance +1) WHERE vertex = v_rec.vertex;
END IF ;
--
IF SELECT
NOT EXISTS
(
SELECT 1 FROM graph WHERE vertex = v_rec.vertex AND vertex_order = 0
)
THEN
UPDATE tmp_matrix SET label = TRUE , is_finish = TRUE WHERE vertex = v_rec.vertex;
END IF ;
END LOOP;
UPDATE tmp_matrix SET label = TRUE WHERE vertex = current_id ;
--
SELECT
vertex
INTO
current_id
FROM
tmp_matrix
WHERE
NOT label AND
distance < 999999 ;
SELECT
distance
INTO
current_distance
FROM
tmp_matrix
WHERE
vertex = current_id ;
SELECT
EXISTS (SELECT 1 FROM tmp_matrix WHERE label = FALSE )
INTO
not_visit ;
IF current_id IS NULL
THEN
not_visit = FALSE ;
END IF;
END LOOP;
Geben Sie die resultierende Verfügbarkeitsmatrix zurück
SELECT
vertex ,
label ,
distance ,
is_finish
FROM
tmp_matrix
WHERE
distance != 999999 ;
Gibt an, ob der Mitarbeiter mit check_id der angegebenen start_id untergeordnet ist
Holen Sie sich die Verfügbarkeitsmatrix für start_id (siehe oben).
IF EXISTS
( SELECT distance FROM tmp_matrix WHERE vertex = check_id )
THEN
RETURN TRUE;
ELSE
RETURN FALSE;
END IF;
Liste der untergeordneten Mitarbeiter für diesen (Pfad von Chef start_id zu Mitarbeiter finish_id)
Holen Sie sich die Verfügbarkeitsmatrix für start_id (siehe oben).
Füllen Sie die Pfadtabelle zwischen den Tabellen start_id und finish_id
current_id = finish_id ;
result[1] = finish_id ;
WHILE current_id != start_id
LOOP
SELECT
par.id
FROM
( SELECT
id
FROM
graph
WHERE
vertex_order = 0 AND
edge IN (SELECT
edge
FROM
graph
WHERE
vertex = current_id AND vertex_order = 1 )) par
JOIN tmp_matrix m ON ( par.id = m.vertex )
INTO
parent_id
LIMIT 1 ;
SELECT
array_append( result , parent_id )
INTO
result ;
--
current_id = parent_id ;
END LOOP;
Das Ergebnis im Array- Ergebnis wird als Pfadsatz- ID in umgekehrter Reihenfolge gebildet. Zur Vereinfachung der Anzeige kann das Array auf beliebige Weise umgekehrt werden.