where语句在SAS中搜索多个变量的任意组合中的2个值

时间:2017-08-25 13:31:53

标签: sql sas sas-macro

我正在尝试使用Proc SQl搜索双重条件。 我想搜索v1,v2,v3,v4 ...... v10中存在'TTT'和'RRR'的时间 所以它可能是TTT在V1中,RRR在v10或V1和V2中。有很多组合,但我不想明显地输入每个组合。 同时我还想使用OR语句来搜索v1-v10中仅包含('TTT'和'RRR')或('GGG')的变量。我一直在四处寻找,想想也许是一个可行的案例,但我不这么认为,我还需要把它作为一个PROC SQL。

我知道下面的代码是错误的,因为它是一个更长的版本,但是,只是为了获得我的意思:

WHERE date BETWEEN &start. AND &end. 
AND ( ((V1 = 'TTT' and V2 ='RRR') OR (V1 = 'GGG')) OR ((V1 = 'TTT' and V3 ='RRR') OR (V1 = 'GGG')) OR ((V1 = 'TTT' and V4 ='RRR') OR (V1 = 'GGG')) ...)

谢谢, 非常赞赏!

基于@Tom答案的更新版本

 data
diag_table;
input v1 $ v2 $ v3 $ v4 $ v5 $;
cards;
TTT . . RRR .
GGG . . . .
. RRR . . TTT
. . . . .
FFF . . . .
. . RRR1 . .
TTT . . GGG .
. RRR . GGG .
run;
proc print data=diag_table;
quit;

proc sql;
create table diag_found  as
select *
from diag_table
WHERE (whichc('TTT',v1,v2,v3,v4,v5) and whichc('RRR',v1,v2,v3,v4,v5)) or (whichc('GGG',v1,v2,v3,v4,v5));
quit;
proc print data=diag_found;
quit;

enter image description here

这段代码的唯一问题是它也抓住了行的情况 包含GGG + RRR和GGG + TTT 我尝试在两组中添加括号,但它没有改变任何东西。

更新: @Tom和@Joe:

是的,我想我的确意味着带有AND的XOR。

因此,如果A = TTT B = RRR C = GGG (A和B)XOR C

A + B组合OR C

enter image description here

谢谢!

3 个答案:

答案 0 :(得分:4)

您可以使用WHICHC()功能执行您想要的操作。

where whichc('TTT',v1,v2) and whichc('RRR',v1,v2)

请注意,在SQL中使用它有点困难,因为您无法使用变量列表,因此您需要明确列出每个变量名称whichc('TTT',v1,v2,v3,v4,v5),而不是仅使用变量列表whichc('TTT', of v1-v5),就像在数据步骤中一样。

不确定单独使用GGG是什么意思。但如果你指的是没有TTT或RRR的GGG那么你可以使用这样的逻辑。

where (whichc('TTT',v1,v2) and whichc('RRR',v1,v2))
   or (whichc('GGG',v1,v) and not (whichc('TTT',v1,v2) or whichc('RRR',v1,v2)))

答案 1 :(得分:2)

我认为你在这里不需要任何特别复杂的东西;你会在user2877959的答案中看到的关键概念是将字符串连接成一个长字符串,所以你只需要一个调用(或者在我的情况下,只需要三个简单的调用)。数据步骤比在sql中更容易,但无论哪种方式都可以。

我使用CATX和分隔符来确保“RR”| “RTTT”也不匹配。然后我们只使用FIND找到匹配的字符串。

data have;
  input (v1-v10) (:$3.);
  datalines;
AAA BBB CCC DDD EEE FFF GGG HHH III JJJ
KKK LLL MMM NNN OOO PPP QQQ RRR SSS TTT
UUU VVV WWW XXX YYY ZZZ AAA BBB CCC DDD
GGG TTT RRR AAA BBB CCC DDD EEE FFF HHH
;;;;
run;

proc sql;
  select * from have
      WHERE ( 
           find(catx('|',v1,v2,v3,v4,v5,v6,v7,v8,v9,v10),'RRR') and 
           find(catx('|',v1,v2,v3,v4,v5,v6,v7,v8,v9,v10),'TTT')
          ) ne
          (find(catx('|',v1,v2,v3,v4,v5,v6,v7,v8,v9,v10),'GGG') > 0
          )
    ;
quit;

当然,视图可以处理WHERE子句,如果你也想要它。

我修改了代码以添加XOR组合;基本上它包含GGG或TTT + RRR但不包含GGG + TTT + RRR。这可以通过简单地比较两个布尔结果(注意我将>0添加到第二个以使其评估为真/假;第一个将通过and评估为真/假)。

如果你真的希望排除GGG + RRR,你必须添加一些额外的标准;您可能只是更好地将“has RRR”,“具有TTT”和“GGG”的值分配给三个变量(在视图中或在PROC SQL SELECT查询中),然后评估它们而不是必须做一堆find / whichn / etc。

答案 2 :(得分:-2)

你可以试试正则表达式。有点像这样:

where prxmatch('/(TTT.*RRR|RRR.*TTT)|GGG/',cats(v1,v2,v3,v4,v5,v6,v7,v8,v9,v10));