Hallo zusammen,
ich habe Daten in 2 Spalten:
Mitarbeiter Kontrollierender Mitarbeiter
Datensatz1 15 17
Datensatz2 37 27
Datensatz3 18
Datensatz4 27 18
.
.
.
Der Mitarbeiter 15 wird also von Mitarbeiter 17 kontrolliert, Mitarbeiter 37 von Mitarbeiter 27, Mitarbeiter 18 wird von niemandem kontrolliert, Mitarbeiter 27 von Mitarbeiter 18, usw.
Nun kann man erkennen, dass Mitarbeiter 37 von Mitarbeiter 27 kontrolliert wird, der wiederum von Mitarbeiter 18 kontrolliert wird. Mitarbeiter 18 würde am Ende der Kette stehen, da er von niemandem kontrolliert wird. Er ist also in der höchsten Ebene.
Es herrscht folglich folgende Beziehung: 37 --> 27 --> 18.
Nun möchte ich in meinem Datensatz alle dieser Beziehungen bis zur höchsten Ebene finden. Die Funktion soll also die Beziehungen untereinander aufzeigen und die Daten danach am Besten folgendermaßen ausgeben:
Mitarbeiter Kontrollierender Mitarbeiter
Datensatz2 37 27
Datensatz4 27 18
Datensatz3 18
Neue Ausgabe mit dem nächsten Zusammenhang
Datensatzx xx yy
Datensatzy yy zz
Datensatzz zz
Ich habe leider bisher keine Idee, wie ich diese Auswertung gestalten soll.
Vielen Dank im Voraus für eure Mühen.
LG
Hallo @Katrin11,
willkommen in den SAS Support Communities und speziell bei CoDe SAS!
Im englischsprachigen Hauptforum wurden ähnliche Aufgabenstellungen schon mehrmals diskutiert. Ein Beispiel, das mir ganz gut zu passen scheint und zu dem sogar verschiedene Lösungen gepostet wurden (darunter eine vom berühmten Paul Dorfman ["hashman"]), ist unter folgendem Link zu finden: https://communities.sas.com/t5/SAS-Programming/Get-ancestors-for-each-children/m-p/490584
Hilft das erst einmal weiter? In jedem Fall werden wir eine Lösung finden.
Viele Grüße
Reinhard
Das ist ein typisches Graphenproblem.
Jeder Mitarbeiter ist ein Knoten in diesem Graphen. Und der kontrollierende Mitarbeiter ist der Knoten, der auf den zu kontrollierenden zeigt.
Du legst ein Array an für alle Mitarbeiter. In den Array-Index 15 kommt die 17, weil die 17 die 15 kontrolliert.
Also ma[15]=17.
Oder du kannst es auch andersherum machen: ma[17]=15.
Das hängt davon ab, ob ein MA zwei andere kontrollieren kann.
Wenn das Array fertig gefüllt ist, springst du einfach durch und hast deine Liste.
Wenn du dann noch wissen willst, welche Gruppen zusammen gehören, google mal nach "Zusammenhangskomponente".
Man könnte die "Zusammenhänge" anhand der Nummer des Mitarbeiters der untersten Hierarchieebene identifizieren, also eine Liste dieser niemand anderen kontrollierenden Mitarbeiter erstellen und dann für jeden von ihnen die Hierarchie bis ganz nach oben durchgehen. Etwa so:
/* Erzeugen von Testdaten */
data have;
input ma ktr;
cards;
15 17
37 27
18 .
27 18
;
/* Erstellen der Liste von Mitarbeitern, die keinen kontrollieren */
proc sql;
create table unten as
(select ma from have)
except
(select ktr from have);
quit;
/* Auflisten der Hierarchien "von unten nach oben" */
data zshge;
if _n_=1 then do;
dcl hash h(dataset:'have(where=(n(ktr)))');
h.definekey('ma');
h.definedata('ktr');
h.definedone();
end;
zshg+1;
set unten;
do while(not h.find());
output;
ma=ktr;
ktr=.;
end;
output;
run;
Der letzte Datastep ist durch ein paar Anpassungen aus der erwähnten Lösung von Paul Dorfman aus der anderen Diskussion entstanden. Vorausgesetzt wird insbesondere, dass jeder Mitarbeiter von höchstens einem direkt kontrolliert wird (jeder weitere Kontrollierende würde nicht in die Hash-Tabelle gelangen) und es keine "Schleifen" in der Hierarchie gibt (letztere würden durch den PROC-SQL-Step eliminiert).
hallo Katrin,
ich würde es über ein SAS-Format lösen. Mitarbeiter - kontrollierender Mitarbeiter. Verarbeitet werden dann alle Mitarbeiter, die keine kontrollierenden Mitarbeiter sind. In einer Schleife wird der Mirarbeiter formatiert, der kontrollierende Mitarbeiter zum Mitarbeiter, formatiert usw.
data have;
input ma ktr;
cards;
15 17
37 27
18 .
27 18
;
run;
* Format erzeugen: Mitarbeiter - kontrollierender Mitarbeiter;
data formatdaten;
retain fmtname type ("ktr", "N");
set have(where=(label) rename=(ma=start ktr=label)) end=ende;
output;
if ende then do;
hlo = 'O';
label = '';
output;
end;
run;
proc format cntlin=formatdaten;
run;
* alle kontrollierenden Mitarbeiter in Makrovariable;
proc sql noprint;
select distinct ktr into :ktrs separated by ', '
from have
where ktr;
quit;
%put &=ktrs;
* Verarbeitung der reinen Mitarbeiter (unterste Ebene);
data ergebnis(keep= ma ergebnis);
set have (where=(ma not in (&ktrs.))); * reine MAs;
ergebnis = strip(ma); * initialisieren;
do while (length(put(ma,ktr.)) > 1); * solange es einen KTR gibt;
ergebnis = catx('-',ergebnis, put(ma,ktr.));
ma = input(put(ma,ktr.),best.); * KTR wird zu MA der nächsten Runde;
end;
run;
Ein wenig off-topic, aber ist schon aufgefallen, dass alle Posts hier in CoDe von ThalGarak geliked werden? Schon etwas seltsam.
@andreas_lds schrieb:
Ein wenig off-topic, aber ist schon aufgefallen, dass alle Posts hier in CoDe von ThalGarak geliked werden? Schon etwas seltsam.
Ja, auch dass die Likes meist binnen einiger Sekunden eintreffen (Bot?). Ich habe das gestern per Mail an communities@sas.com gemeldet. (In einem ähnlichen Fall vor einiger Zeit wurde der betreffende Account gesperrt.)
hallo Katrin,
sorry, ich hatte übersehen, dass Du eine spezielle Ausgabe brauchst. Das Prinzip bleibt aber wie eben beschrieben: formatieren.
data have;
input ma ktr;
cards;
15 17
37 27
18 .
27 18
;
run;
* Format erzeugen: Mitarbeiter - kontrollierender Mitarbeiter;
data formatdaten(drop=ktr);
retain fmtname type ("ktr", "N");
set have(where=(ktr) rename=(ma=start)) end=ende;
label=strip(put(ktr,best.));
output;
if ende then do;
hlo = 'O';
label = '';
output;
end;
run;
proc format cntlin=formatdaten;
run;
* alle kontrollierenden Mitarbeiter in Makrovariable;
proc sql noprint;
select distinct ktr into :ktrs separated by ', '
from have
where ktr;
quit;
%put &=ktrs;
* Verarbeitung;
data ergebnis(keep= ma ktr);
set have(where=(ma not in (&ktrs.))); * reine MAs;
do while (put(ma,ktr.) ne ''); * solange es einen KTR gibt;
ktr = input(put(ma,ktr.),best.); * kontrollierender Mitarbeiter;
output;
ma = ktr; * KTR wird zu MA der nächsten Runde;
end;
ktr = .;
output;
run;
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!