SAS/SQL 动态排序变量
SAS/SQL Ordering Variables Dynamically
我正在尝试以特定方式组织一个数据集,其中包含一个变化的变量列表。我遇到的问题是我并不总是知道我的数据集中将拥有的实际变量数。我之前在变量列表是静态的数据语句之后使用 PROC SQL
语句或 RETAIN
语句完成了此操作。
我的数据是这样的:
APPNUM DATE REASON1 REASON2 REASON3 REASON4 NAME1 NAME2 NAME3 NAME4
123 1/1/2017 X Y Z A Jon Mary Tom Suzie
我希望它看起来像这样:
APPNUM DATE REASON1 NAME1 REASON2 NAME2 etc
123 1/1/2017 X Jon Y Mary etc
使用 sql 或保留语句很容易做到这一点。但是,我正在使用循环等将这些变量拉到一起,并且显示的变量数量取决于我的输入数据。有些日子可能有 20 个 REASON/NAME 实例,而其他日子可能每个都有 1 个实例。
我尝试了下面的代码来提取变量名列表,然后对 APPNUM、DATE 进行排序,最后按变量名的最后一位排序。 IE。 1,1,2,2,3,3 - 但我没有成功。该列表被正确存储 - 没有错误,但在解析 &VARLIST 的值时。他们没有按预期订购。有没有人尝试过并完成这个?
PROC SQL;
SELECT NAME INTO :VARLIST SEPARATED BY ','
FROM DICTIONARY.COLUMNS
WHERE LIBNAME = 'WORK'
AND MEMNAME = 'SFINAL'
ORDER BY NAME, SUBSTR(NAME,LENGTH(NAME)-1);
QUIT;
上面的代码会这样排序:
APPNUM, DATE, NAME1...2...3..., REASON1...2...3...
而不是:
APPNUM, DATE, NAME1, REASON1, NAME2, REASON2....
两个问题。
首先,您在 ORDER BY
上的顺序是倒序的。
其次,您的SUBSTR()
调用不正确。最后你有一个任意长度的数字。你不知道会有多少个字符。最好的办法是读取该数字字符串,转换为数字,然后按此排序。
data test;
array name[20];
array reason[20];
format appnum best. date date9.;
run;
proc sql noprint;
SELECT NAME INTO :VARLIST SEPARATED BY ','
FROM DICTIONARY.COLUMNS
WHERE LIBNAME = 'WORK'
AND MEMNAME = 'TEST'
and (upcase(NAME) like 'NAME%' or upcase(NAME) like 'REASON%')
ORDER BY input(compress(compress(name,'name'),'reason'),best.), NAME ;
quit;
%put &varlist;
proc sql noprint;
create table test2 as
select APPNUM, DATE, &varlist
from test;
quit;
我正在尝试以特定方式组织一个数据集,其中包含一个变化的变量列表。我遇到的问题是我并不总是知道我的数据集中将拥有的实际变量数。我之前在变量列表是静态的数据语句之后使用 PROC SQL
语句或 RETAIN
语句完成了此操作。
我的数据是这样的:
APPNUM DATE REASON1 REASON2 REASON3 REASON4 NAME1 NAME2 NAME3 NAME4
123 1/1/2017 X Y Z A Jon Mary Tom Suzie
我希望它看起来像这样:
APPNUM DATE REASON1 NAME1 REASON2 NAME2 etc
123 1/1/2017 X Jon Y Mary etc
使用 sql 或保留语句很容易做到这一点。但是,我正在使用循环等将这些变量拉到一起,并且显示的变量数量取决于我的输入数据。有些日子可能有 20 个 REASON/NAME 实例,而其他日子可能每个都有 1 个实例。
我尝试了下面的代码来提取变量名列表,然后对 APPNUM、DATE 进行排序,最后按变量名的最后一位排序。 IE。 1,1,2,2,3,3 - 但我没有成功。该列表被正确存储 - 没有错误,但在解析 &VARLIST 的值时。他们没有按预期订购。有没有人尝试过并完成这个?
PROC SQL;
SELECT NAME INTO :VARLIST SEPARATED BY ','
FROM DICTIONARY.COLUMNS
WHERE LIBNAME = 'WORK'
AND MEMNAME = 'SFINAL'
ORDER BY NAME, SUBSTR(NAME,LENGTH(NAME)-1);
QUIT;
上面的代码会这样排序:
APPNUM, DATE, NAME1...2...3..., REASON1...2...3...
而不是:
APPNUM, DATE, NAME1, REASON1, NAME2, REASON2....
两个问题。
首先,您在 ORDER BY
上的顺序是倒序的。
其次,您的SUBSTR()
调用不正确。最后你有一个任意长度的数字。你不知道会有多少个字符。最好的办法是读取该数字字符串,转换为数字,然后按此排序。
data test;
array name[20];
array reason[20];
format appnum best. date date9.;
run;
proc sql noprint;
SELECT NAME INTO :VARLIST SEPARATED BY ','
FROM DICTIONARY.COLUMNS
WHERE LIBNAME = 'WORK'
AND MEMNAME = 'TEST'
and (upcase(NAME) like 'NAME%' or upcase(NAME) like 'REASON%')
ORDER BY input(compress(compress(name,'name'),'reason'),best.), NAME ;
quit;
%put &varlist;
proc sql noprint;
create table test2 as
select APPNUM, DATE, &varlist
from test;
quit;