递归添加到SAS中的数据table
Recursively add to a data table in SAS
我是 SAS 新手。我需要进行 x- 次迭代来填充名为 MYRS
.
的数据集
每次迭代需要JOIN TABLE1
with (TABLE2
+ MYRS
) MINUS MYRS
table 中已有的记录。
然后,我需要用额外的匹配更新 MYRS
table。目标是跟踪一系列电子邮件。
MYRS
本质上是 TABLE1
的副本并包含匹配记录。有点棘手。 (简化模式)。 Table1
可以有 DUPS。
例如
TABLE1:
ID | EMAIL1 | EMAIL2 | EMAIL3 | EMAIL4|
1 | A | s | d | F
2 | g | F | j | L
3 | z | x | L | v
4 | z | x | L | v
2 | g | F | j | L
TABLE2:
EMAIL
A
MYRS (starts as empty dataset)
EMAIL1 | EMAIL2 | EMAIL3 | EMAIL4
逻辑:TABLE1
的电子邮件与 TABLE2
中的电子邮件匹配。因此需要显示此记录。其他记录与 TABLE2
中的任何内容都不匹配。但是因为Record1
和Record2
共享the same ALTERNATIVE email
F,所以也需要显示Record2
。但是因为 Record2
和 Record3
共享相同的替代电子邮件 L,所以 Record3
也需要显示。所以第四...
proc sql;
SELECT TABLE1.id,
TABLE1.email1,
TABLE1.email2,
TABLE1.email3,
TABLE1.email4
FROM TABLE1
INNER JOIN (
SELECT EMAIL
FROM TABLE2
UNION
SELECT EMAIL1 AS EMAIL
FROM MYRS
UNION
SELECT EMAIL2 AS EMAIL
FROM MYRS
UNION
SELECT EMAIL3 AS EMAIL
FROM MYRS
UNION
SELECT EMAIL4 AS EMAIL
FROM MYRS
)
ON EMAIL=EMAIL1 OR EMAIL=EMAIL2 OR EMAIL=EMAIL3 OR EMAIL=EMAIL4
WHERE TABLE1.id NOT IN (
SELECT DISTINCT ID
FROM MYRS
)
quit;
如何创建以下逻辑:
- 将其包装成某种函数
- 在sql执行之前,计算MYDS中的记录数量并保存计数
- 执行SQL并更新MYDS
- 计算 MYDS 中的记录数量
- 如果MYDS计数没有变化,停止执行
- 否则,转到#3
我是 SAS 的新手(准确地说是 3 天),正在尝试将所有内容放在一起。 (如果我要在 Java 中这样做,我会使用上面的逻辑)
这是一个宏方法,它主要遵循您的逻辑,但首先转换您的数据,input/output 是一个 ID
的列表(您可以使用它轻松地收发电子邮件) .
这段代码可能会介绍很多您不熟悉的 SAS 功能,但下面的评论和解释应该有所帮助。如果仍有任何不清楚的地方,请查看链接或添加评论。
它需要输入数据:
inData
:带有 ID
和 EMAIL*
变量的 TABLE1
matched
:已知通缉名单ID
s
它returns:
matched
:更新的通缉名单 ID
s
/* Wrap the processing in a macro so that we can use a %do loop */
%macro looper(maxIter = 5);
/* Put all the emails in one column to make comparison simpler */
proc transpose data = inData out = trans (rename = (col1 = email));
by ID;
var email:;
run;
/* Initialise the counts for the %where condition */
%let _nMatched = 0;
%let nMatched = 1;
%let i = 0;
/* Loop until no new IDs are added (or maximum number of iterations) */
%do %while(&_nMatched. < &nMatched. and &i < &maxIter.);
%let _nMatched = &nMatched.;
%let i = %eval(&i. + 1);
%put NOTE: Loop &i.: &nMatched. matched.;
/* Move matches to a temporary table */
proc datasets library = work nolist nowarn;
delete _matched;
change matched = _matched;
quit;
/* Get new matched IDs */
proc sql noprint;
create table matched as
select distinct c.ID
from _matched as a
left join trans as b
on a.ID = b.ID
left join trans as c
on b.email = c.email;
/* Get new count */
select count(*) into :nMatched from matched;
quit;
%end;
%mend looper;
%looper(maxIter = 10);
有趣的部分是:
proc transpose
:将输入转换为深度 table 以便所有电子邮件地址都在一个变量中,这使得编写电子邮件比较逻辑更简单(需要更少的重复)并将数据放入采用一种格式,以便您在必要时更轻松地清理电子邮件地址(想想 upcase()
、strip()
等)。
%macro %mend
:用于定义macro的语句。这是必要的,因为您不能在开放代码中使用宏逻辑或循环。我还添加了一个参数,以便您了解它是如何工作的。
%let
and select into :
: Two ways to create macro variables。宏变量用前缀 &
引用,用于在执行前将文本插入 SAS 程序。
%do %while() %end
:在宏内执行循环的方法之一。其中的代码将重复 运行,直到条件计算结果为 false。
proc datasets
:对数据集和库执行管理任务的过程。此处用于删除和重命名临时 tables.
我是 SAS 新手。我需要进行 x- 次迭代来填充名为 MYRS
.
每次迭代需要JOIN TABLE1
with (TABLE2
+ MYRS
) MINUS MYRS
table 中已有的记录。
然后,我需要用额外的匹配更新 MYRS
table。目标是跟踪一系列电子邮件。
MYRS
本质上是 TABLE1
的副本并包含匹配记录。有点棘手。 (简化模式)。 Table1
可以有 DUPS。
例如
TABLE1:
ID | EMAIL1 | EMAIL2 | EMAIL3 | EMAIL4|
1 | A | s | d | F
2 | g | F | j | L
3 | z | x | L | v
4 | z | x | L | v
2 | g | F | j | L
TABLE2:
EMAIL
A
MYRS (starts as empty dataset)
EMAIL1 | EMAIL2 | EMAIL3 | EMAIL4
逻辑:TABLE1
的电子邮件与 TABLE2
中的电子邮件匹配。因此需要显示此记录。其他记录与 TABLE2
中的任何内容都不匹配。但是因为Record1
和Record2
共享the same ALTERNATIVE email
F,所以也需要显示Record2
。但是因为 Record2
和 Record3
共享相同的替代电子邮件 L,所以 Record3
也需要显示。所以第四...
proc sql;
SELECT TABLE1.id,
TABLE1.email1,
TABLE1.email2,
TABLE1.email3,
TABLE1.email4
FROM TABLE1
INNER JOIN (
SELECT EMAIL
FROM TABLE2
UNION
SELECT EMAIL1 AS EMAIL
FROM MYRS
UNION
SELECT EMAIL2 AS EMAIL
FROM MYRS
UNION
SELECT EMAIL3 AS EMAIL
FROM MYRS
UNION
SELECT EMAIL4 AS EMAIL
FROM MYRS
)
ON EMAIL=EMAIL1 OR EMAIL=EMAIL2 OR EMAIL=EMAIL3 OR EMAIL=EMAIL4
WHERE TABLE1.id NOT IN (
SELECT DISTINCT ID
FROM MYRS
)
quit;
如何创建以下逻辑:
- 将其包装成某种函数
- 在sql执行之前,计算MYDS中的记录数量并保存计数
- 执行SQL并更新MYDS
- 计算 MYDS 中的记录数量
- 如果MYDS计数没有变化,停止执行
- 否则,转到#3
我是 SAS 的新手(准确地说是 3 天),正在尝试将所有内容放在一起。 (如果我要在 Java 中这样做,我会使用上面的逻辑)
这是一个宏方法,它主要遵循您的逻辑,但首先转换您的数据,input/output 是一个 ID
的列表(您可以使用它轻松地收发电子邮件) .
这段代码可能会介绍很多您不熟悉的 SAS 功能,但下面的评论和解释应该有所帮助。如果仍有任何不清楚的地方,请查看链接或添加评论。
它需要输入数据:
inData
:带有ID
和EMAIL*
变量的 TABLE1matched
:已知通缉名单ID
s
它returns:
matched
:更新的通缉名单ID
s
/* Wrap the processing in a macro so that we can use a %do loop */
%macro looper(maxIter = 5);
/* Put all the emails in one column to make comparison simpler */
proc transpose data = inData out = trans (rename = (col1 = email));
by ID;
var email:;
run;
/* Initialise the counts for the %where condition */
%let _nMatched = 0;
%let nMatched = 1;
%let i = 0;
/* Loop until no new IDs are added (or maximum number of iterations) */
%do %while(&_nMatched. < &nMatched. and &i < &maxIter.);
%let _nMatched = &nMatched.;
%let i = %eval(&i. + 1);
%put NOTE: Loop &i.: &nMatched. matched.;
/* Move matches to a temporary table */
proc datasets library = work nolist nowarn;
delete _matched;
change matched = _matched;
quit;
/* Get new matched IDs */
proc sql noprint;
create table matched as
select distinct c.ID
from _matched as a
left join trans as b
on a.ID = b.ID
left join trans as c
on b.email = c.email;
/* Get new count */
select count(*) into :nMatched from matched;
quit;
%end;
%mend looper;
%looper(maxIter = 10);
有趣的部分是:
proc transpose
:将输入转换为深度 table 以便所有电子邮件地址都在一个变量中,这使得编写电子邮件比较逻辑更简单(需要更少的重复)并将数据放入采用一种格式,以便您在必要时更轻松地清理电子邮件地址(想想upcase()
、strip()
等)。%macro %mend
:用于定义macro的语句。这是必要的,因为您不能在开放代码中使用宏逻辑或循环。我还添加了一个参数,以便您了解它是如何工作的。%let
andselect into :
: Two ways to create macro variables。宏变量用前缀&
引用,用于在执行前将文本插入 SAS 程序。%do %while() %end
:在宏内执行循环的方法之一。其中的代码将重复 运行,直到条件计算结果为 false。proc datasets
:对数据集和库执行管理任务的过程。此处用于删除和重命名临时 tables.