使用 proc sql 将具有迭代值的新列插入 table 中的每个唯一行
Insert new column with iterative value to every unique rows in a table using proc sql
我可以知道是否有技术可以将具有迭代值的新列插入 table 中的每个唯一行吗?
示例:
TABLE 有
ID name
1 John
2 Matt
3 Pete
现在,我有一个计数器 = 3,我想将每个计数器值最多添加 3 到 table HAVE 中的每个唯一 ID。
TABLE 想要
ID name count
1 John 1
1 John 2
1 John 3
2 Matt 1
2 Matt 2
2 Matt 3
3 Pete 1
3 Pete 2
3 Pete 3
我可以使用 by 和 first.var:
的组合使用数据步骤来做到这一点
data want;
set have;
by ID;
if first.ID then do;
do i = 1 to count;
output;
end;
end;
run;
我这里的主要问题是 运行时间,数据步按顺序处理数据集,可能需要一些时间才能 运行。我想知道这是否可以使用 proc sql 来完成?
使用内置功能proc sql
无法特别轻松地做到这一点。一种解决方案是,如果您有某种计数或数字 table。那么你可以这样做:
select id, t.name, n.n
from t join
numbers n
on n.n <= :counter;
事实上,如果您的 ID 是连续的且没有间隙(如您的示例所示),您可以使用自连接:
select t.id, t.name, n.id as count
from t join
t n
on n.id <= :counter;
如果你知道具体值,你可以构造一个union all
查询:
select id, name, 1 as count from t
union all
select id, name, 2 as count from t
union all
select id, name, 3 as count from t;
现代 SQL 现在具有简化此过程的构造(例如 window 函数和递归 CTE)。但是,这些不能直接在 proc sql
.
中使用
结果集是外连接,如果有 N 行都不同,则将包含 N2 行。
示例:
SASHELP.CLASS 有 19 个不同的行,每行将有 18 个重复,得到 19**2 或 361 行。
帮助程序查询创建一个仅包含 count
值的帮助程序 table(我称它们为 index
)
data class;
set sashelp.class;
run;
proc sql;
* monotonic() trusted by Richard for this create/select only ;
* commented out for fear of mono (pun intended);
* create table indexes as
select index from
( select distinct *, monotonic() as index from class);
* one mark per distinct row;
create table distinct_marks(keep=mark) as
select distinct *, 1 as mark from class;
* create table of traditionally computed monotonic indexes;
data indexes(keep=index);
set distinct_marks;
index + 1;
run;
proc sql;
create table want as
select
self.*,
each.index
from
class as self
cross join
indexes as each
;
quit;
将以上方法与您原来的方法进行比较
proc sql noprint;
select count (*) into :count trimmed
from
( select distinct * from class );
quit;
data want;
set class;
do _n_ = 1 to &count;
output;
end;
run;```
Regardless of what approach you choose, OUTER JOINS can get BIG QUICK, and thus cause lots of time consuming disk i/o.
我可以知道是否有技术可以将具有迭代值的新列插入 table 中的每个唯一行吗?
示例:
TABLE 有
ID name
1 John
2 Matt
3 Pete
现在,我有一个计数器 = 3,我想将每个计数器值最多添加 3 到 table HAVE 中的每个唯一 ID。
TABLE 想要
ID name count
1 John 1
1 John 2
1 John 3
2 Matt 1
2 Matt 2
2 Matt 3
3 Pete 1
3 Pete 2
3 Pete 3
我可以使用 by 和 first.var:
的组合使用数据步骤来做到这一点data want;
set have;
by ID;
if first.ID then do;
do i = 1 to count;
output;
end;
end;
run;
我这里的主要问题是 运行时间,数据步按顺序处理数据集,可能需要一些时间才能 运行。我想知道这是否可以使用 proc sql 来完成?
使用内置功能proc sql
无法特别轻松地做到这一点。一种解决方案是,如果您有某种计数或数字 table。那么你可以这样做:
select id, t.name, n.n
from t join
numbers n
on n.n <= :counter;
事实上,如果您的 ID 是连续的且没有间隙(如您的示例所示),您可以使用自连接:
select t.id, t.name, n.id as count
from t join
t n
on n.id <= :counter;
如果你知道具体值,你可以构造一个union all
查询:
select id, name, 1 as count from t
union all
select id, name, 2 as count from t
union all
select id, name, 3 as count from t;
现代 SQL 现在具有简化此过程的构造(例如 window 函数和递归 CTE)。但是,这些不能直接在 proc sql
.
结果集是外连接,如果有 N 行都不同,则将包含 N2 行。
示例:
SASHELP.CLASS 有 19 个不同的行,每行将有 18 个重复,得到 19**2 或 361 行。
帮助程序查询创建一个仅包含 count
值的帮助程序 table(我称它们为 index
)
data class;
set sashelp.class;
run;
proc sql;
* monotonic() trusted by Richard for this create/select only ;
* commented out for fear of mono (pun intended);
* create table indexes as
select index from
( select distinct *, monotonic() as index from class);
* one mark per distinct row;
create table distinct_marks(keep=mark) as
select distinct *, 1 as mark from class;
* create table of traditionally computed monotonic indexes;
data indexes(keep=index);
set distinct_marks;
index + 1;
run;
proc sql;
create table want as
select
self.*,
each.index
from
class as self
cross join
indexes as each
;
quit;
将以上方法与您原来的方法进行比较
proc sql noprint;
select count (*) into :count trimmed
from
( select distinct * from class );
quit;
data want;
set class;
do _n_ = 1 to &count;
output;
end;
run;```
Regardless of what approach you choose, OUTER JOINS can get BIG QUICK, and thus cause lots of time consuming disk i/o.