【问题标题】:Hash Merge key variable has spaces哈希合并键变量有空格
【发布时间】:2019-05-09 10:18:21
【问题描述】:

我目前正在学习 Hash 合并并在这里有点挣扎。

第一个问题是在进行哈希合并时,应该对哪个表进行哈希处理,以及使用 set 语句读取哪个表?在下面的示例中,Tablex 位于 SQL 服务器上,并且有几百万条记录。 Table1 的记录数是 Tablex 的 10%,并且在我的工作临时文件夹中。

我只想从 TableX 中选择出现在 Table1 中的记录,下面的代码会是一个好方法吗?如果我也想使用条件来调节 TableX,我会怎么做让我们说开放日期 > '01 DEC 2010'd

还有可能有一个带有空格的变量作为关键变量还是我必须做重命名位?

Data merges;
    if 0 then set server.Tablex(rename='account number'n= 
                  account_number_full2) table1;
    if _n_ = 1 then do;
        declare hash tab2(dataset:'table1');
                tab2.defineKey('Account_Number_full');
                tab2.defineData(all:'YES');
                tab2.defineDone();
    end;


    set Tablex(rename='account number'n= account_number_full2);


    if tab2.find(key:account_number_full2) = 0
    then output;
run;

【问题讨论】:

  • 记住远程表中的每条记录都将被传输到 SAS 进行评估。减少“传输”的唯一方法是将table1 上传到服务器并在 SQL 服务器中执行传递连接。

标签: hash merge sas


【解决方案1】:

让我们试着通过一个例子来理解。您在 set 语句中提到的内容在这种情况下作为输出 has1 表。你的哈希表是有的。如果 n = 0 则 set have1 仅用于设置表。您不需要 all 用于哈希表,因为您没有将这些数据用于最终输出表。

data have;
input id value $;
datalines;
1   A
2   B
3   C
4   D
;

data have1;
  input id date:mmddyy10.;
 format date mmddyy10.;
 datalines;
 2 01/15/2018
 3 01/01/2017
;

Data merges;
if 0 then set have1;
if _n_ = 1 then do;
    declare hash tab2(dataset:'have');
            tab2.defineKey('id');
            tab2.defineDone();
end;


set have1;


if tab2.find(key:id) = 0
;
run;

如果您想包含日期,您可以使用 where 子句作为数据集选项,如下所示。

    Data merges;
if 0 then set have1;
if _n_ = 1 then do;
 declare hash tab2(dataset:'have');
        tab2.defineKey('id');
        tab2.defineDone();
 end;


  set have1(where= (date gt '01JAN2018'd));


  if tab2.find(key:id) = 0;
  run;

【讨论】:

  • 小心双重设置方法。这将自动保留have1中的所有变量。
  • 如果 0 则设置 have1;这仅用于读取参数匹配的描述符部分
  • 正确;但是,如果您使用散列左连接执行此方法,例如rc = h.Find();,则与该散列变量关联的所有数据列都将保留到下一次匹配。这可能会导致意外结果。使用长度语句初始化变量比使用双重集合语句更安全。
【解决方案2】:

仅当 SAS 会话已打开时,散列中的变量 names 才能包含任何字符

option validvarname = any;

如果您要导入 Excel 数据或具有不符合典型名称命名约定的列的数据源 - 以 _ 或字母开头,后跟任意数量的 _、字母或数字,则可能会设置此选项。

在 DATA 步代码中引用异常命名的列时,您必须使用 SAS 名称文字语法(引用引用后跟 N),但是,当将列名称传递给哈希构造函数(作为字符串)时,您将使用名称而不是名称文字:

"<column-name>"N

示例代码:

options validvarname = any;

data have;
  "my key name is spacey"N = "key-1";  **** name-literal syntax used here;
  x = 123;
run;

data _null_;
  if 0 then set have; * prep pdv;
  if _n_ = 1 then do;
    declare hash h(dataset:'have');
    h.defineKey("my key name is spacey");  **** name with spaces passed here;
    h.defineData("x");
    h.defineDone();
  end;

  'my key name is spacey'N = "key-0";   **** name-literal used here;
  rc = h.find();
  put rc= x=;

  'my key name is spacey'N = "key-1";  **** name-literal used here;
  rc = h.find();
  put rc= x=;    
run;

至于加入。

  • 设置远程表
  • where 应用于远程表。 SQLSRV 数据库引擎会将条件传递给 SQL,并在通过“线路”将数据发送回 DATA 步骤之前应用它。
  • 如果tablex和lookup中的key变量名相同,可以使用更简单的hash.find()hash.find(key:&lt;expression&gt;) 仅在名称不对齐时才需要,或者在成为合适的查找之前必须转换一个域中的键(例如在密码上查找登录匹配只有在输入的文本经过散列然后比较之后才有效掌握登录表)

【讨论】:

    猜你喜欢
    • 2013-05-04
    • 1970-01-01
    • 2016-01-06
    • 2018-02-12
    • 1970-01-01
    • 2016-05-29
    • 2017-12-18
    • 1970-01-01
    • 2019-03-03
    相关资源
    最近更新 更多