2016-11-11 337 views
2

在PROC SQL中,我需要选择所有行中名为“NAME”的列不包含多个值“abc”,“cde”和“fbv”在这些值之前或之后。所以我这样做:SAS PROC SQL不包含一个语句中的多个值

SELECT * FROM A WHERE 
    NAME NOT CONTAINS "abc" 
    AND 
    NAME NOT CONTAINS "cde" 
    AND 
    NAME NOT CONTAINS "fbv"; 

它工作得很好,但我想如果我们有一百个条件将是一个头痛。所以我的问题是 - 我们可以在PROC SQL中的单个语句中完成此操作吗? 我尝试使用这样的:

SELECT * FROM A WHERE 
    NOT CONTAINS(NAME, '"abc" AND "cde" AND "fbv"'); 

但这并不在PROC SQL工作,我收到以下错误:

ERROR: Function CONTAINS could not be located.

我不想使用等。

回答

2

你可以使用正则表达式,我想。

data a; 
input name $; 
datalines; 
xyabcde 
xyzxyz 
xycdeyz 
xyzxyzxyz 
fbvxyz 
;;;; 
run; 

proc sql; 

SELECT * FROM A WHERE 
    NAME NOT CONTAINS "abc" 
    AND 
    NAME NOT CONTAINS "cde" 
    AND 
    NAME NOT CONTAINS "fbv"; 


SELECT * FROM A WHERE 
    NOT (PRXMATCH('~ABC|CDE|FBV~i',NAME)); 
quit; 

尽管如此,您不能使用CONTAINS。

+0

工作很好,谢谢! 〜表示我假设的通配符? – puk789

+1

'〜'只是一个分隔符,你必须用正则表达式中没有使用的任何分隔符来开始和结束一个正则表达式。正则表达式匹配'任何地方',除非你锚定它们开始或结束。 – Joe

+0

有道理,再次感谢你:) – puk789

0

您可以使用NOT IN

SELECT * FROM A WHERE 
    NAME NOT IN ('abc','cde','fbv'); 
+0

但我需要它排除任何包含例如'abc',无论'abc'之前或之后有多少个字符。 – puk789

0

如果项目的数量超过合理数量内搭的代码,你可以创建一个表(以下work.words)来存储的话,并遍历它来检查事件:

data work.values; 
input name $; 
datalines; 
xyabcde 
xyzxyz 
xycdeyz 
xyzxyzxyz 
fbvxyz 
; 
run; 

data work.words; 
length word $50; 
input word $; 
datalines; 
abc 
cde 
fbv 
; 
run; 


data output; 
set values; 

/* build a has of words */ 
length word $50; 
if _n_ = 1 then do; 
    /* this runs once only */ 
    call missing(word); 
    declare hash words (dataset: 'work.words'); 
    words.defineKey('word'); 
    words.defineData('word'); 
    words.defineDone(); 
end; 

/* iterate hash of words */ 
declare hiter iter('words'); 
rc = iter.first(); 
found = 0; 
do while (rc=0); 
    if index(name, trim(word)) gt 0 then do; /* check if word present using INDEX function */ 
     found= 1; 
     rc = 1; 
    end; 
    else rc = iter.next(); 
end; 
if found = 0 then output; /* output only if no word found in name */ 
drop word rc found; 
run;