BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
hk24
Obsidian | Level 7

I'm trying to select the top 1 record belonging to each group in proc sql, but not been able to identify a correct way to do it in proc sql. I'm trying to find top account tied to the store with transactions and total_sales ordered in descending manner. In simple words, one account may be tied to multiple stores, so within each account, I'm trying to filter the top record with highest transactions and sales.

 

I have an excel file which I'm importing using proc import, but providing a sample table below as an example.

 

accountstore_numtransactionssales
1011000390
10110006170
10510155156
10212349200
10112347189
102123411267
10510305170

 

I'm initially grouping the account and store_num by sum of transactions and sales in descending order and then used PROC RANK to assign rank.

 
Below is the code that I have tried so far.

```

proc import datafile="/myfolder/eg.xlsx"
out=fileg dbms=xlsx replace;
run;

 

proc sql;
create table tempp as
Select account, store_num, sum(transactions) as total_Transactions, sum(sales) as Total_Sales, 
from fileg
group by account, store_num
order by total_transactions desc, Total_Sales desc;
quit;

 

proc sql;

create table main2 as
select * from tempp
order by account;
quit;

 

proc rank data=main2 out=result ties=dense descending;
by account;
var total_transactions;
ranks transRank;
run;
proc print data=result n;
run;

```

The output of 'result' looks like the one below:

accountstore_numtotal_transactionstotal_salestransRank
101123471892
101100092601
1021234204671
105101551561
105103051701

 

I want my final table to look like the one below so that it ranks and filter outs the first record for each account having highest transactions. In case of a tie in the rank due to same transactions, the highest sales will be used to provide the rank. 

 

accountstore_numtotal_salestotal_transactions
102123446720
10110002609
10510301705

 

PROC SQL GROUP BY Having in proc sql 

1 ACCEPTED SOLUTION

Accepted Solutions
Patrick
Opal | Level 21

SAS SQL doesn't provide window/analytics functions so any selection based on sort order is not that easy to implement. 

With SAS I'd go for a combination of SQL and data step (option 1). It can also be done with a nested SLQ but it's not "pretty" (option 2).

data have;
input account store_num transactions sales;
datalines;
101 1000 3 90
101 1000 6 170
101 1234 7 189
102 1234 9 200
102 1234 11 267
105 1030 5 170
105 1015 5 156
;

/* option 1 */
proc sql;
  create table inter as
  select 
    account,
    store_num,
    sum(sales) as total_sales,
    sum(transactions) as total_transactions
  from have
  group by account, store_num
  order by account, total_transactions, total_sales
  ;
quit;

data want1;
  set inter;
  by account;
  if last.account;
run;

/* option 2 */
proc sql;
  create table want2 as
  select *
  from
  (
    select *
    from 
      (
      select 
        account,
        store_num,
        sum(sales) as total_sales,
        sum(transactions) as total_transactions
      from have
      group by account, store_num
      )
    group by account
    having max(total_transactions)=total_transactions
  )
  group by account
  having max(total_sales)=total_sales
  ;
quit;

View solution in original post

3 REPLIES 3
ballardw
Super User

Please carefully define, or provide starting data and result, exactly what you mean by "top account tied to the store".

 

 

hk24
Obsidian | Level 7
I have edited my question with sample data and code that I have tried so far.
Patrick
Opal | Level 21

SAS SQL doesn't provide window/analytics functions so any selection based on sort order is not that easy to implement. 

With SAS I'd go for a combination of SQL and data step (option 1). It can also be done with a nested SLQ but it's not "pretty" (option 2).

data have;
input account store_num transactions sales;
datalines;
101 1000 3 90
101 1000 6 170
101 1234 7 189
102 1234 9 200
102 1234 11 267
105 1030 5 170
105 1015 5 156
;

/* option 1 */
proc sql;
  create table inter as
  select 
    account,
    store_num,
    sum(sales) as total_sales,
    sum(transactions) as total_transactions
  from have
  group by account, store_num
  order by account, total_transactions, total_sales
  ;
quit;

data want1;
  set inter;
  by account;
  if last.account;
run;

/* option 2 */
proc sql;
  create table want2 as
  select *
  from
  (
    select *
    from 
      (
      select 
        account,
        store_num,
        sum(sales) as total_sales,
        sum(transactions) as total_transactions
      from have
      group by account, store_num
      )
    group by account
    having max(total_transactions)=total_transactions
  )
  group by account
  having max(total_sales)=total_sales
  ;
quit;

SAS Innovate 2025: Call for Content

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!

Submit your idea!

Mastering the WHERE Clause in PROC SQL

SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 3 replies
  • 4532 views
  • 1 like
  • 3 in conversation