Filter SAS代码,用于过滤数字流(ID)中由下划线分隔的特定ID的记录

Filter SAS代码,用于过滤数字流(ID)中由下划线分隔的特定ID的记录,filter,sas,Filter,Sas,我有一个字段,其中包含如下记录: 1. 1234_2400_800_15001 2. 8800_1414_2626 3. 100_3000_8009 4. 800 5. 1392_22132_4212 6. 2213_1700_600 7. 1392_1100_22134 8. 2213 我需要一个SAS代码来标记或过滤ID为800和2213的所有记录,我的代码将返回我上面给出的所有8条记录,而它应该只返回与ID完全匹配的记录,没有其他前面或后面的数字。正确的代码应返回: 1.

我有一个字段,其中包含如下记录:

 1. 1234_2400_800_15001
 2. 8800_1414_2626
 3. 100_3000_8009
 4. 800
 5. 1392_22132_4212
 6. 2213_1700_600
 7. 1392_1100_22134
 8. 2213
我需要一个SAS代码来标记或过滤ID为800和2213的所有记录,我的代码将返回我上面给出的所有8条记录,而它应该只返回与ID完全匹配的记录,没有其他前面或后面的数字。正确的代码应返回:

1. 1234_2400_800_15001
4. 800
6. 2213_1700_600
8. 2213
我试图使用(800或800或800或800)通过LIKE查找匹配项,但它将“uuu”视为一个单独的字符串


添加我使用的代码:

proc-sql;
从work.test创建表test作为select*,将“abc”作为Flag1
哪里
2019年11月1日至2020年10月31日之间的pd_dt,以及
(clm_lvl_abp_id类似于“%800%”时的情况)
或clm_lvl_abp_id,如“%\u 800%”
或clm_lvl_abp_id,如“%”800%,然后是1
其他0
结束)=1;
退出

使用不含任何whildcard的contains代替like。 要在字符串的开头或结尾查找ID,只需在每一侧添加下划线即可

数据地垒;
填充数据线truncover;
格式行$55。;
输入行$;
数据线;
1234_2400_800_15001
8800_1414_2626
100_3000_8009
800
1392_22132_4212
2213_1700_600
1392_1100_22134
2213
proc-sql;
从地垒中选择*
其中“| | |带(线)| |”包含“|800|”
或“| | |带(线)| |”包含“|2213|”;
退出

使用不含任何whildcard的contains代替like。 要在字符串的开头或结尾查找ID,只需在每一侧添加下划线即可

数据地垒;
填充数据线truncover;
格式行$55。;
输入行$;
数据线;
1234_2400_800_15001
8800_1414_2626
100_3000_8009
800
1392_22132_4212
2213_1700_600
1392_1100_22134
2213
proc-sql;
从地垒中选择*
其中“| | |带(线)| |”包含“|800|”
或“| | |带(线)| |”包含“|2213|”;
退出

对于LIKE运算符,下划线是单字符通配符。要把它当作一个普通的角色,你需要逃避它

clm_lvl_abp_id like '%800^_%' escape '^'
但是你会发现使用搜索“800”这个词更容易。它将返回单词的起始位置。您可以告诉它将u视为分隔符。如果找不到该单词,则返回值为零。SAS将零视为假,将任何其他值视为真

where pd_dt between '01Nov2019'd and '31Oct2020'd
  and indexw(trim(clm_lvl_abp_id),'800','_')
例如:

data have;
  input rownum idlist $50.;
  found = 0<indexw(trim(idlist),'800','_');
cards;
1 1234_2400_800_15001
2 8800_1414_2626
3 100_3000_8009
4 800
5 1392_22132_4212
6 2213_1700_600
7 1392_1100_22134
8 2213
;

对于LIKE运算符,下划线是单字符通配符。要把它当作一个普通的角色,你需要逃避它

clm_lvl_abp_id like '%800^_%' escape '^'
但是你会发现使用搜索“800”这个词更容易。它将返回单词的起始位置。您可以告诉它将u视为分隔符。如果找不到该单词,则返回值为零。SAS将零视为假,将任何其他值视为真

where pd_dt between '01Nov2019'd and '31Oct2020'd
  and indexw(trim(clm_lvl_abp_id),'800','_')
例如:

data have;
  input rownum idlist $50.;
  found = 0<indexw(trim(idlist),'800','_');
cards;
1 1234_2400_800_15001
2 8800_1414_2626
3 100_3000_8009
4 800
5 1392_22132_4212
6 2213_1700_600
7 1392_1100_22134
8 2213
;

您可以使用正则表达式匹配函数
PRXMATCH
测试字符串中的简单或复杂模式

例如:

正则表达式模式检查目标标记
800
2213
是否在下划线(
\uu
)分隔的字符串中出现

data have;
input rownum idlist $50.;
cards;
 1. 1234_2400_800_15001
 2. 8800_1414_2626
 3. 100_3000_8009
 4. 800
 5. 1392_22132_4212
 6. 2213_1700_600
 7. 1392_1100_22134
 8. 2213
;

data want;
  set have;

  place = prxmatch ('/(^|_)(800|2213)($|_)/', strip(idlist));
  if place;
run;
对于更长的
idlist
和更多要匹配的目标id,可以使用SQL查询和存在式where,利用
indexw
函数(@Tom)查找至少包含一个目标
id
idlist
s

范例

* 1,000 lists;

data have;
  call streaminit(2021);

  length idlist $200;
  do _n_ = 1 to 1000;
    call missing(idlist);
    do i = 1 to rand('integer', 8);
      id = rand('integer', 1200);
      idlist = catx('_', idlist, id);
    end;
    output;
  end;
  keep idlist;
run;

* 100 targets;

data id_target;
  length id $4;
  call streaminit(2021);
  do _n_ = 1 to 100;
    id = cats(rand('integer',1200));
    output;
  end;
run;

proc sql;
  create table want as
  select * 
  , countw(idlist,'_') as ids_count
  , (select count(distinct id) from id_target
     where indexw (idlist, trim(id), '_')) as ids_hit
  from have
  where exists (
    select * from id_target
    where indexw (idlist, id, '_')
  )
  ;
quit;

您可以使用正则表达式匹配函数
PRXMATCH
测试字符串中的简单或复杂模式

例如:

正则表达式模式检查目标标记
800
2213
是否在下划线(
\uu
)分隔的字符串中出现

data have;
input rownum idlist $50.;
cards;
 1. 1234_2400_800_15001
 2. 8800_1414_2626
 3. 100_3000_8009
 4. 800
 5. 1392_22132_4212
 6. 2213_1700_600
 7. 1392_1100_22134
 8. 2213
;

data want;
  set have;

  place = prxmatch ('/(^|_)(800|2213)($|_)/', strip(idlist));
  if place;
run;
对于更长的
idlist
和更多要匹配的目标id,可以使用SQL查询和存在式where,利用
indexw
函数(@Tom)查找至少包含一个目标
id
idlist
s

范例

* 1,000 lists;

data have;
  call streaminit(2021);

  length idlist $200;
  do _n_ = 1 to 1000;
    call missing(idlist);
    do i = 1 to rand('integer', 8);
      id = rand('integer', 1200);
      idlist = catx('_', idlist, id);
    end;
    output;
  end;
  keep idlist;
run;

* 100 targets;

data id_target;
  length id $4;
  call streaminit(2021);
  do _n_ = 1 to 100;
    id = cats(rand('integer',1200));
    output;
  end;
run;

proc sql;
  create table want as
  select * 
  , countw(idlist,'_') as ids_count
  , (select count(distinct id) from id_target
     where indexw (idlist, trim(id), '_')) as ids_hit
  from have
  where exists (
    select * from id_target
    where indexw (idlist, id, '_')
  )
  ;
quit;

我们建议添加一些代码行,这样我们可以提供一个适合您的解决方案。在叙述中正确使用AND和OR是非常重要的。您希望记录的ID列表包含
800
、或
2213
、或两者。作为编程规范,我认为
800
2213
意味着两者都必须存在。我们建议添加一些代码行,这样我们就可以提供适合您的解决方案。在叙述中,AND和OR的正确使用非常重要。您希望记录的ID列表包含
800
、或
2213
、或两者。作为一个编程规范,我认为
800
2213
意味着两者都必须存在。非常感谢您如此快速的响应。当另一个代码正在运行时,Quick想要询问上面的代码是否会返回所有这些所需的记录:1234_2400_800_15001、800、2213_1700_600&2213稍微调整一下就完成了这项工作。非常感谢你,你真是太好了!不过,我最终还是通过PRXMATCH实现了这一点:-)非常感谢您的快速响应。当另一个代码正在运行时,Quick想要询问上面的代码是否会返回所有这些所需的记录:1234_2400_800_15001、800、2213_1700_600&2213稍微调整一下就完成了这项工作。非常感谢你,你真是太好了!不过,我最终还是通过PRXMATCH实现了:-)如果您提供两种解决方案,那么最好两次回答一个问题。你不仅可以在每一个问题上都赢得声誉,而且对读者来说更清晰,而且会使最受欢迎的解决方案出现在顶部。我并没有真正回答如何用类似的方法完全解决问题。如果你提供两个解决方案,最好回答一个问题两次。你不仅可以在每个人身上赢得声誉,而且对读者来说更清晰,并且会使最受欢迎的解决方案出现在顶部。我没有真正回答如何完全解决这个问题