BookmarkSubscribeRSS Feed
pavank
Quartz | Level 8
data employees;
    input department $ employee $;
    datalines;
Sales John
Sales Mary
HR Alice
HR Bob
IT Eve
IT Charlie
;
run;


proc sql;
    select department,
           catx(',', employee) as employees
    from
        select distinct department,
               employee
        from employees
    ) group by employee,department;
quit;

how to get comma separated employees list for each department using proc sql

11 REPLIES 11
PaigeMiller
Diamond | Level 26

Please tell us what you would do with these comma separated lists by department, so that we may be able to come up with another method that doesn't involve SQL.

--
Paige Miller
yabwon
Onyx | Level 15

First remark: Maxim 14: Use the right tool.

Do it the SAS way:

data employees;
    input department $ employee $;
    datalines;
Sales John
Sales Mary
HR Alice
HR Bob
IT Eve
IT Charlie
IT Zelda
;
run;

data Want;
  set employees;
  by department notsorted;
  length list $ 100;
  retain list;
  if first.department then list="";

  list = catx(",",list,employee);

  if last.department;
  keep department list;
run;
proc print data=want;
run; 

Second remark:

@ChrisNZ : "You can't do it in SAS",

Me: "Hold my beer" 😉 😉

Assuming you know the maximum number of employees in a department (and you can count that) you could try this:

data employees;
    input department $ employee $;
    datalines;
Sales John
Sales Mary
HR Alice
HR Bob
IT Eve
IT Charlie
IT Zelda
;
run;

data Want;
  set employees;
  by department notsorted;
  length list $ 100;
  retain list;
  if first.department then list="";

  list = catx(",",list,employee);

  if last.department;
  keep department list;
run;
proc print;
run; 

proc sql;
select max(m)
into :maxDept /* max number of people in a the department */
from
(select count(department) as m 
 from employees
 group by department
)
;

create table wantSQL_base as
  select distinct department, employee, count(employee) as n
  from
  (
    select a.*
    from employees as a
    join employees as b
    on a.department = b.department
    and a.employee<=b.employee
  )
  group by department, employee
;

create table wantSQL_final as
  select distinct  
  t1.department, catx(","
  %macro loop1(n);
    %do n=1 %to &n;
      ,t&n..employee
    %end;
  %mend;
  %loop1(&maxDept.)
  ) as list
  from
    %macro loop2(n);
    %do n=1 %to &n;
      %if &n>1 %then left join;
      (select department, employee from wantSQL_base where n=&n.) as t&n.
      %if &n>1 %then on t&n..department = t%eval(&n.-1).department;
    %end;
    %mend;
    %loop2(&maxDept.)
;
quit;


proc print data=wantSQL_base;
run; 
proc print data=wantSQL_final;
run; 

(But remember the fact you CAN do something does not mean you SHOULD do it!)

 

Bart

 

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



Kurt_Bremser
Super User

I want to suggest a small optimization to your code:

data Want;
  set employees;
  by department notsorted;
  length list $ 100;
  retain list;
  if first.department
  then list = employee;
  else list = catx(",",list,employee);
  if last.department;
  keep department list;
run;

This way you do only one assignment at FIRST.

yabwon
Onyx | Level 15

Good point! Thanks Kurt (@Kurt_Bremser)

 

Bart

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



ChrisNZ
Tourmaline | Level 20

@ChrisNZ : "You can't do it in SAS",

I only said SQL can't do it in SAS, not that SAS can't do it.

You are (cleverly!) supplementing the limitation of SQL by adding a layer of macro language logic, but the limitation remains.

yabwon
Onyx | Level 15

You right, the limitation remains, that's why I'm fully support (2x👍) those ballot ideas you shared. Unfortunately, I'm afraid that SAS (the firm) won't be very eager to add new features to SAS (language and 9 engine)... With all that "Viya-centrism"... 😞

But hopefully Workbench will give more drive to make some good BASE engine extensions. 

 

Bart

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



FreelanceReinh
Jade | Level 19

Here's another just-for-fun approach, suitable (without further additions) only for small examples like your sample data or sashelp.class, if any:

proc sql noprint;
select catx(':',department,employee,department) into :x separated by '|'
from employees
order by department, employee;

create table want as
select department, scan(substr(tranwrd("&x",cats(':',department,'|',department,':'),', '),find("&x",cats(department,':'))),2,':') as emp_list
from (select distinct department from employees);
quit;
Tom
Super User Tom
Super User

That is not something that SQL is designed to support since it does not look like set operations (or relational algebra).  I know that many databases that use SQL as their query language have enhanced the SQL language to handle such things.  But that is because they did not already have a data manipulation language, like SAS does.

 

I note that your posted data is grouped by department already (but not sorted) so you could process it as is by using the NOTSORTED keyword on the BY statement.  But you probably want to first SORT by the grouping variable (DEPARTMENT).  You might also want to sort within the grouping variable by some other variable that makes sense.  Perhaps seniority in the department? Or in the company? Or just alphabetically by name.  

 

You will also need to decide how long this new character variable needs to be to hold the longest possible list of employees.

 

proc sort data=employees ;
  by department employee;
run;
data want ;
  do until(last.department);
     set employees;
     by department employee;
     length employees $200 ;
     employees = catx(',',employees,employee);
  end;
  keep department employees ;
run;

SAS Innovate 2025: Register Today!

 

Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.


Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 11 replies
  • 1451 views
  • 9 likes
  • 7 in conversation