SAS substr合并

SAS substr合并,sas,match,substr,Sas,Match,Substr,我想我知道关于如何解决这个问题的所有部分,我刚刚遇到了将它们放在一起的问题(除了一个小问题) 我有两个数据集。一个叫“旧id”,一个叫“新id”。旧的“ID”是7个字符(9个包括连字符…例如:EX-123-45)。新的ID格式为9个字符(11个包括hypens…示例:88EX-123-45)。有些旧的_id已转换为新的_id,但前面添加了88或55。所有其他新id前面都有22个,我需要避免这些,因为它们有重复的id作为“旧id”,但前面有22个 我想要做的是能够将“旧id”的信息与“新id”相匹

我想我知道关于如何解决这个问题的所有部分,我刚刚遇到了将它们放在一起的问题(除了一个小问题)

我有两个数据集。一个叫“旧id”,一个叫“新id”。旧的“ID”是7个字符(9个包括连字符…例如:EX-123-45)。新的ID格式为9个字符(11个包括hypens…示例:88EX-123-45)。有些旧的_id已转换为新的_id,但前面添加了88或55。所有其他新id前面都有22个,我需要避免这些,因为它们有重复的id作为“旧id”,但前面有22个

我想要做的是能够将“旧id”的信息与“新id”相匹配,这是旧id的新id(lol)

我知道我可以用

data ID_5;
set new_id;
ID5 = substr(right(id),2);
run;
这去掉了前导的数字,我可以在这方面进行匹配。有两个文件,但我没有办法取回前导变量(据我所知)。 我是否可以编写一个if语句来匹配new_ID中“ID”的最后9个字符是否与旧的_ID匹配。如果new_ID中ID的前导字符=88或55

我拥有的数据看起来像什么以及我想要最终结果是什么的示例

data for old_id.. this also contains 22 overrides (only about 20 though)

location ProductID    destination 
1        EX-123-45    724
1        EX-12A-B3    724      /* not all old ids have an override*/
5        EX-ABC-12    515
5        EX-ABC-14    953
7        22EX-ZYX-12  007
7        22EX-LMN-12  056
新的\u id文件

location ID          destination
1        22EX-123-45  894
1        55EX-123-45  785
5        22EX-987-45  999
5        88EX-ABC-14  881
7        22EX-ZYX-12  678
7        22EX-LMN-12  254
我希望它看起来像什么

location ProductID  destination 
1        22EX-123-45  894
1        55EX-123-45  724  /*old_id overrides destination*/
5        22EX-987-45  999
5        88EX-ABC-14  953  /*old_id overrides destination*/
7        22EX-ZYX-12  007  /*overwrites new_id destination*/
7        22EX-LMN-12  056  /*overwrites new_id destination*/

22中的大多数没有覆盖,因此如果您真的可以通过值的长度来判断变量
id
中的id类型,则使用该值来决定是否需要删除两个字符

if length(id)=9 then old_id=id;
else old_id=substr(id,3);
如果连字符的插入也不一致,您可能还需要删除它们

if length(compress(id,'-'))=7 then old_id=compress(id,'-');
else old_id=compress(substr(id,3),'-');

只需创建一个要合并的新变量,就可以解决保留原始的新id的问题

data true_new new;
  set new_id;

  length match_id $9;

  if substr(id, 1,2) = '22' then call missing(match_id);
  else if substr(id,1,2) in ('88', '55') then match_id = substr(id,3);
  else match_id = id;

  if missing(match_id) then output true_new;
  else output new;

run;

现在,我将根据
match\u id
字段将
new
old\u id
匹配,然后将
true\u new
附加到结果数据集中。这些可以一步完成,但我觉得这更简洁。

首先,让我们将您的列表转换为我们可以使用的实际数据集

data old_id ;
  input location ProductID :$11.  destination $ ;
cards;
1  EX-123-45  724
1  EX-12A-B3  724      /* not all old ids have an override*/
5  EX-ABC-12  515
5  EX-ABC-14  953
7  22EX-ZYX-12  007
7  22EX-LMN-12  056
;
data new_id;
  input location ID :$11. destination $ ;
cards;
1  22EX-123-45 894
1  55EX-123-45 785
5  22EX-987-45 999
5  88EX-ABC-14 881
7  22EX-ZYX-12  678
7  22EX-LMN-12  254
;
现在只需将它们连接起来,并使用COALESCE()函数来选择正确的值。您的联接条件需要以不同方式处理以
22
开头的值

proc sql ;
 create table want as
   select a.location
        , a.id as productid
        , coalesce(b.destination,a.destination) as destination
   from new_id a
   left join old_id b
   on (b.productid = substr(a.id,3) and a.id not eqt '22')
   or (b.productid = a.id and a.id  eqt '22')

   order by 1,2
 ;
quit;

为什么前两个具有不同的目标值?如果旧的值覆盖了新的值,那么它们不都应该是724吗?在什么文件中?假设您指的是“what i want”文件,这是因为所有以22开头的id都可能具有基于最后9个字符的错误匹配。他们在旧的_id文件中已经写入了自己的覆盖,我对匹配合并没有问题,因为他们已经正确格式化,请提供详细信息/案例,说明如何覆盖以22开头的id值。我已经更新了文件,以包含他们的22个对应项,我应该从一开始就这样做。我很抱歉,我喜欢这样的想法,制作一个只有88和55的文件,然后删除它们并合并。我的另一个文件也覆盖了'22',但大部分覆盖了旧的\u ID。因此,使用这个逻辑,我只需与覆盖文件合并两次。正如我在没有这个更新逻辑的情况下所做的那样(所以它只做22次),然后使用更新的逻辑覆盖旧的_id。虽然这里有一个有趣的注释,但真正的新文件排除了最后25行的id和一些目的地。Tom,很抱歉延迟了回复。这对我来说是忙碌的一天,但我已经更新了问题代码,以便更好地显示我想要的。很抱歉,在我弹出一个会议之前出现了混乱,没有时间回顾我写的内容。我已经在sas的数据集中把它们作为“旧id”和“新id”了。我已经重写了你的代码来解释这一点,但到目前为止,它已经运行了10分钟,并且一直在运行。新的_id文件包含每个位置以及位置和目标的所有可能组合,因此它是一个相当大的文件(数百万行),您知道一种更有效的方法吗?我让它运行了一段时间,但它仍然无法执行。注意:此查询的执行涉及执行一个或多个无法优化的笛卡尔乘积联接。