Help using Base SAS procedures

Counting distinct within various groups

Reply
Occasional Contributor
Posts: 13

Counting distinct within various groups

Hi All,

Hope someone can help ...

I have the following hypothetical dataset:

MainAccountClientNumAlternativeAccount
AA1A1
AA1A2
AA1A3
AA2A4
AA2A3
BB1B1
BB1B2
CC1

You will note that main account AA has two clients linked to it and accounts BB and CC have one client linked to each. Account CC has no alternative accounts

In account AA, each of the clients have different alternative accounts, but they share 1 (A3)

I want to count how many alternative accounts each client has and how many alternatve account each main account has (without double counting A3 for the first account). The problem is counting only the distinct alternative account numbers when looking at a main account level. I tried using a count(case ...) statement but it will always double count the A3 account and i cannot use a nested statement to say only count it once when is is not distinct ...

My ideal final dataset needs to like like follow: (that is: NumAccount_AltAccounts for Account AA must show 4 not 5)

MainAccountClientNumNumClient_AltAccountsNumAccount_AltAccounts
AA134
AA224
BB122
CC100

Thanks!!

Super User
Super User
Posts: 6,502

Re: Counting distinct within various groups

Key idea is to use COUNT(DISTINCT varname) to get the counts.

Then you can create two queries that group by different variables and merge the results to get your final table.

I shortened the variable names to make it easier to type.

data have ;

  input (a b c) ($) @@;

cards;

AA 1 A1 AA 1 A2 AA 1 A3 AA 2 A4 AA 2 A3 BB 1 B1 BB 1 B2 CC 1 .

;

proc sql ;

create table want as

  select x.*,y.cnt2

  from

   (select distinct a,b,count(distinct c) as cnt1 from have group by a,b) x

  ,(select distinct a,count(distinct c) as cnt2 from have group by a) y

  where x.a = y.a

  order by 1,2

;

quit;

data _null_;

  set want;

  put (_ALL_) (=);

run;

a=AA b=1 cnt1=3 cnt2=4

a=AA b=2 cnt1=2 cnt2=4

a=BB b=1 cnt1=2 cnt2=2

a=CC b=1 cnt1=0 cnt2=0

Respected Advisor
Posts: 3,124

Re: Counting distinct within various groups

Tom's SQL is no doubt the most pithy approach, here is a data step using 2XDOW:

data have;

infile cards truncover;

input (MainAccount ClientNum AlternativeAccount) (:$);

cards;

AA 1 A1

AA 1 A2

AA 1 A3

AA 2 A4

AA 2 A3

BB 1 B1

BB 1 B2

CC 1

;

proc sort data=have;

by MainAccount ClientNum AlternativeAccount;run;

data want;

  array aa(100) $2. _temporary_;

  do _n_=1 by 1 until (last.MainAccount);

  set have;

by MainAccount;

  if AlternativeAccount not in aa then aa(_n_)=AlternativeAccount;

  end;

  num_client=0;

  num_account=100-cmiss(of aa(*));

  do until (last.MainAccount);

  set have;

by MainAccount ClientNum AlternativeAccount;

if not missing(AlternativeAccount) then num_client+first.AlternativeAccount;

if last.ClientNum then do; output;num_client=0;end;

  end;

call missing(of aa(*));

drop AlternativeAccount;

run;

proc print;run;

Haikuo

Super User
Posts: 9,682

Re: Counting distinct within various groups

Yeah. Tom 's code is absolutely right and fast. I just want to rewrite it by using sub-query which is also a powerful tool of SQL as its cartesian product . Don't be offended , TOM.

data have ;

  input (a b c) ($) @@;

cards;
AA 1 A1 AA 1 A2 AA 1 A3 AA 2 A4 AA 2 A3 BB 1 B1 BB 1 B2 CC 1 .
;

proc sql ;
create table want as
select distinct a,b,count(distinct c) as cnt1,(select count(distinct c) from have where a=x.a ) as cnt2
  from have  as x
   group by a,b
;
quit;

Ksharp

Occasional Contributor
Posts: 13

Re: Counting distinct within various groups

Hi all,

Thanks ... this helps a lot.

Regards,

Mahesh

Ask a Question
Discussion stats
  • 4 replies
  • 13571 views
  • 3 likes
  • 4 in conversation