【问题标题】:How to join two databases using proc sql using two variables如何使用 proc sql 使用两个变量连接两个数据库
【发布时间】:2021-12-28 14:40:28
【问题描述】:

我正在尝试加入两个基于变量 office_id 和 office_id_flag 的数据集,每个数据集都有 50,000 个观察值。

data1 变量

  1. grp
  2. 年龄
  3. 西班牙裔
  4. 身份证
  5. 种族
  6. 精神疾病
  7. mental_ill_dx
  8. office_id
  9. office_id_flag

data2 变量

  1. er_vis
  2. adm_hr
  3. psych_hosp
  4. psych_vis
  5. 地区
  6. region_rpc
  7. 收费
  8. office_id
  9. office_id_flag

我首先在数据步骤合并过程中尝试了这个,因为我知道它是如何工作的,结果数据集有 50,000 个观察值和 17 个变量,这对我来说很有意义。 合并代码:

proc sort data=data1; by office_id; run;
proc sort data=data2; by office_id; run;

data work.merge_datastep;
    merge data1 (in=dem) data2 (in=hosp);
    by office_id;
    if dem and hosp;
run;
*53000 observations and 17 variables;

我尝试了很多 SQL 合并类型,每一种都生成一个包含 56000 个观察值和 17 个变量的数据集,这没有任何意义。

这是我在 SQL 中尝试过的:

proc sql;
create table sql_outerjoin as 
 select * 
 from data1 full outer join data2 on data1.office_id=data2.office_id;
quit;


proc sql;
create table sql_leftjoin as 
 select * from data1 left outer join data2 on data1.office_id=data2.office_id;
quit;

proc sql;
create table work.sql_innerjoin as
select data1.*, data2.*
from work.data1, work.data2
where data1.office_id=data2.office_id;
quit; 

proc sql ;
create table sql_try1 as 
select one.*, two.*
from data1 as one
left join data2 as two
on (one.office_id = two.office_id and one.office_id_flag= two.office_id_flag);
quit;


proc sql;
create table sql_try3 as
select coalesce(a.office_id, b.office_id) as ID
from data1 a
full join data2 b
on a.ID = b.ID;
quit;

proc sql;
  create table sparcs_1 as
  select * 
  from data1, data2
  where data1.office_id=data2.office_id;
quit;


proc sql;
create table work.sql_leftjoin2 as
select s.*, d.*
from work.data1 as s left join work.data2 as d
on s.office_id=d.office_id;
quit; 

此外,这些 proc sql 尝试中的每一个都导致了这些错误:

  1. 警告:变量 office_id 已存在于文件 WORK 中。whatever_table_name
  2. 警告:变量 office_id_flag 已存在于文件 WORK 中。whatever_table_name

我希望最终结果与 datastep 合并过程相同,并包含所有变量和 50,000 个观察值,在 office_id 和 office_id_flag 上匹配。

我已经超出了我的深度,显然是在黑暗中拍摄。有人有什么建议吗?

【问题讨论】:

  • 为什么对同一个 OFFICE_ID 值有多个观察值?在每个输入数据集中唯一标识观察的变量是什么?它变大了多少?重复项是否可能仅针对 OFFICE_ID 的一个值?也许是缺少值或意味着 id 未知的代码?

标签: join merge sas proc-sql


【解决方案1】:

如果在数据步骤合并中观察的数量没有增加,但在 SQL 连接中增加,那么您的数据在合并/连接键上不是唯一的。当存在重复行时,SAS 不会增加合并中的行数——它也可能不会做你想做的事,但它可能会做一些可以容忍的事情。但是,SQL 会为每个组合生成(取决于您如何操作)额外的行。

如何解决这个问题?确保您有一个唯一的连接键,其中 both 数据集中没有一对(或更多)行共享相同的值。或者,为您拥有的数据考虑正确的连接类型 - 它可能需要汇总数据。

如果数据实际上唯一的,则可能只是您没有包含您想要的确切组合。

proc sql;
  create table sparcs_1 as
  select * 
  from data1, data2
  where data1.office_id=data2.office_id
    and data1.office_id_flag=data2.office_id_flag
  ;
quit;

proc sql;
  create table sparcs_1 as
  select * 
  from data1 inner join data2
  on data1.office_id=data2.office_id
    and data1.office_id_flag=data2.office_id_flag
  ;
quit;

这两个变量都需要行匹配两个变量并且来自两个表。但这不是您的 SAS 数据步骤合并所做的 - 它仅取决于 office_id,因此它可能会给出不同的结果。您可能无法在 SQL 中完美复制此连接 - 无需添加某种行编号 - 因为 SAS 进行合并的方式不同,通常不是您真正想要在 SQL 中执行的操作.

其次,您的警告是因为您正在做这样的事情:

select a.*, b.* 

如果两个数据集中都有相同的变量,那么您需要两次。因此发出警告。如果连接键是唯一重叠的变量,这实际上不是问题 - 那么结果就是你想要的,只是带有警告 - 但你可以通过明确列出你想要的变量来删除它至少一个 em> 的表。最佳做法是根本不使用*,但这是可以理解的,尤其是当一张表有很多变量时。

【讨论】:

  • 谢谢,乔!这就解释了警告和额外的观察。我现在已经尝试过这段代码:proc sql ; create table sql_try4 as select data1.*, data2.er_vis, data2.adm_hr, data2.psych_hosp, data2.psych_vis, data2.region, data2.region_rpc, data2.charges from data1 left join data2 on (data1.pme_id = data2.pme_id and data1.pme_id_flag= data2.pme_id_flag); quit; 并且仍然看到额外的观察结果。我将如何总结数据?
【解决方案2】:

谢谢,乔!您的 cmets 非常有帮助。

我最终根据观察行添加了一个行号(来自这个先前提出的问题https://communities.sas.com/t5/SAS-Procedures/PROC-SQL-QUESTION-How-to-add-a-row-number-to-a-table-observation/td-p/167770),并在 SAS 和 proc sql 中测试了结果数据集。

代码在这里:

proc sql;
  create table rows1 as
    select monotonic() as row, *
      from work.data1;
quit;

proc sql; 
    create table rows2 as 
        select monotonic() as row, *
            from work.data2;
quit;

proc sql ;
create table sql_rowmerge1 as 
select rows1.*, row2.er_vis, row2.adm_hr, row2.psych_hosp, row2.psych_vis, row2.region, row2.region_rpc, row2.charges
from rows1
left join rows2
on (rows1.row = rows2.row and rows1.office_id = rows2.office_id and rows1.office_id_flag= rows2.office_id_flag);
quit;

正如您所建议的,基于 3 个条件变量而不是仅 2 个(可能不是唯一的)变量的合并是以适当的方式将两个数据集组合在一起的原因。生成的数据集现在具有正确的 50,000 个观察值。

再次感谢 - 这太棒了!我学会了一种新方法!

【讨论】:

  • 那么,如果您只是想跳过所有这些障碍,让它像数据步骤代码一样工作,为什么还要使用 PROC SQL 代码呢?只需运行数据步骤。更容易、更快、更清晰。
  • 我同意 - 我宁愿使用数据步骤并用更少的行完成它,但使用 proc sql 是任务的一部分。
  • “作业”?从谁?问他们为什么要你使用不合适的工具?或者,您不理解的数据中可能存在某些使使用 SQL 代码合适的地方?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-03
  • 1970-01-01
相关资源
最近更新 更多