Question

I have this problem, but in SAS. To use the example provided in this question, I have 5 columns of names (name_1, name_2, etc.), and want to output a list in which the names are listed in descending order of frequency:

John     502
Robert   388
William  387
...
...       1

I took the answer to the question referenced above, and surrounded it with "proc sql;" and "quit;":

proc sql;
create table freqs as
SELECT name, COUNT(1)
FROM (           SELECT name_1 AS name FROM mytable
     UNION ALL SELECT name_2 AS name FROM mytable
     UNION ALL SELECT name_3 AS name FROM mytable
     UNION ALL SELECT name_4 AS name FROM mytable
     UNION ALL SELECT name_5 AS name FROM mytable
   ) AS myunion
 GROUP BY name
 ORDER BY COUNT(1) DESC
;
quit;

but am getting:

ERROR: Summary functions are restricted to the SELECT and HAVING clauses only.

I am using SAS 9.2.

Thoughts? Thanks for the help!

Was it helpful?

Solution

You just need to change your ORDER BY expression to reference the second column. I'd also suggest that you assign the COUNT expression result to a SAS variable name (perhaps "freq"):

proc sql; 
   create table freqs as 
   SELECT name
        , COUNT(*) as freq
   FROM (
      SELECT           name_1 AS name FROM mytable
      UNION ALL SELECT name_2 AS name FROM mytable
      UNION ALL SELECT name_3 AS name FROM mytable
      UNION ALL SELECT name_4 AS name FROM mytable
      UNION ALL SELECT name_5 AS name FROM mytable
      ) AS myunion  
   GROUP BY name
   ORDER BY freq DESC;
quit; 

FYI: You can also say ORDER BY 2 DESC to give a relative reference.

OTHER TIPS

Proc SQL does not allow the count(1) in the order by. Try this instead:

proc sql;
    create table freqs as
        SELECT name, COUNT(1) as freqs
        FROM (SELECT name_1 AS name FROM mytable UNION ALL
              SELECT name_2 AS name FROM mytable UNION ALL
              SELECT name_3 AS name FROM mytable UNION ALL
              SELECT name_4 AS name FROM mytable UNION ALL
              SELECT name_5 AS name FROM mytable
             ) AS myunion
         GROUP BY name
         ORDER BY 2 DESC ;
 quit;

I think it allows the column reference.

The following might work as well if the dataset is not too big:

data mytable;
 input (name1-name5) (: $17.) @@;
 cards;
 john henry bob jerry james gary bill john mark gabe
 ;
run;

proc sql;
select 'do name = '
||catq("A2SC", name1,name2,name3,name4,name5)
||'; output; end;' into : nlist separated by ' ' from mytable
 ;
quit;

data test;
&nlist
Run;

proc freq order = freq;
tables name;
run;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top