LesezeichenAbonnierenRSS-Feed abonnieren
Katrin11
Calcite | Level 5

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

 

 

7 ANTWORTEN 7
FreelanceReinh
Jade | Level 19

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

JMS
Obsidian | Level 7 JMS
Obsidian | Level 7

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".

 

FreelanceReinh
Jade | Level 19

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).

HeideTribius
Fluorite | Level 6

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;
andreas_lds
Jade | Level 19

Ein wenig off-topic, aber ist schon aufgefallen, dass alle Posts hier in CoDe von ThalGarak geliked werden? Schon etwas seltsam.

FreelanceReinh
Jade | Level 19

@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.)

HeideTribius
Fluorite | Level 6

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;