2016-11-11 137 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;