2012-09-10 3 views
1

형식의 SAS 해시 조인은 부분 부분 문자열에서 SAS 해시 검색을 수행 할 수 있습니까? 'LongString를'하지만 내 목표 테이블 키가 있습니다 : LIKE 형식 또는 = :

그래서 해시 테이블 키가 포함됩니다 'LongStr'

당신은에 Iterator 객체를 사용할 필요가

답변

1

꽤 좋지는 않지만 원하는 성능 이점을 얻지 못할 수도 있습니다. 또한 문자열 길이와 테이블 크기에 따라 해시 테이블의 모든 요소를 ​​메모리에 넣을 수 없을 수도 있습니다.

트릭은 가능한 모든 하위 문자열을 먼저 생성 한 다음 해시 테이블에서 'multidata'옵션을 사용하는 것입니다.

우리에 대해 일치 할 데이터 집합에 포함 된 단어 만들기 :

data match_attempts; 
    length abbrev $10; 
    input abbrev ; 
    cards; 
L 
Long 
LongO 
LongSt 
LongOther 
; 
run; 
: 우리가 검색 할 용어가 포함 된 데이터 집합을 만들기

data abbreviations; 
    length abbrev $10; 
    set keys; 
    do cnt=1 to length(key); 
    abbrev = substr(key,1,cnt); 
    output; 
    end; 
run; 

: 가능한 모든 문자열 생성

data keys; 
    length key $10 value $1; 
    input key; 
    cards; 
LongString 
LongOther 
; 
run; 

조회 수행 :

Obs abbrev key 
=== ========= ========== 
1 Long  LongString 
2 Long  LongOther 
3 LongO  LongOther 
4 LongSt LongString 
5 LongOther LongOther 

몇 가지 더주의 사항 :

data match; 
    length abbrev key $10; 

    set match_attempts; 

    if _n_ = 1 then do; 
    declare hash h1(dataset:'abbreviations', multidata: 'y'); 
    h1.defineKey('abbrev'); 
    h1.defineData('abbrev', 'key'); 
    h1.defineDone(); 

    call missing(abbrev, key); 
    end; 

    if h1.find() eq 0 then do; 
    output; 
    h1.has_next(result: r); 
    do while(r ne 0); 
     h1.find_next(); 
     output; 
     h1.has_next(result: r); 
    end; 
    end; 

    drop r; 
run; 

출력 (방법 '긴'수익률이 일치주의). 해시 테이블이 like 연산자와 같은 것을 지원하지 않는 이유는 해시 테이블에 레코드를 삽입하기 전에 키를 '해시'하기 때문입니다. 조회가 수행 될 때 조회 할 값은 '해시'된 다음 해시 된 값에 일치가 수행됩니다. 값을 조금만 변경해도 값이 해시되면 완전히 다른 결과가 발생합니다. 2 거의 동일한 문자열을 해싱하는 2 개 전혀 다른 값을 산출, 아래의 예를 보자

data _null_; 
    length hashed_value $16; 
    hashed_value = md5("String"); 
    put hashed_value= hex32.; 
    hashed_value = md5("String1"); 
    put hashed_value= hex32.; 
run; 

출력 :

이 때문에
hashed_value=27118326006D3829667A400AD23D5D98 
hashed_value=0EAB2ADFFF8C9A250BBE72D5BEA16E29 

, 해시 테이블은 like 연산자를 사용할 수 없다.

마지막으로 일부 샘플 데이터의 경우 @vasja 덕분입니다.

+0

해시 테이블에 대한 매우 흥미로운 통찰력에 대해 효율성을 고려하여 vasja의 응답을 받아 들여야했습니다. 두 담당자가 결합 될 수 있는지 확인하십시오 (예 : 히터 대신 다중 데이터 옵션 사용). –

+0

실제로 테이블이 특정 크기에 도달하면 실제로 광산이 더 효율적입니다. @ vasja의 솔루션은 모든 행에 대해 O (N * M/2) 속도로 실행해야합니다. 일치하는 항목을 찾거나 찾을 때까지 반복기를 탐색해야합니다. 평균적으로 데이터 집합의 절반을 반복합니다. 광산은 초기 오버 헤드가 더 높지만, O (N) 시간에 일치하는 것을 발견 할 수 있는데, 이는 obs의 수가 증가함에 따라 훨씬 빠릅니다. 이 시간들이 무엇을 의미하는지 궁금하다면 '빅 오 (Big O)'표기법을 검색해보십시오.작은 데이터 셋의 경우 어쨌든'like '를 사용하여 SQL 조인을 사용하는 것이 더 좋습니다. 해시 테이블을 지나치게 복잡하게 만들지 마십시오. –

+1

실제 상황을 설명합니다. 해시를 반복하기 위해 @vasjas solution 1ms가 걸리면 각 행에 대해 결과를 얻으려면 평균 0.5ms가 소요됩니다. 큰 테이블에 10M 행이 있고 SAS가 총 83 분 30 초가되는 10M 행을 탐색하는 데 30 초가 걸린다 고합니다. 내 솔루션에서 검색 할 시간은 검색 용어에 해시 함수를 적용하고 메모리에서 결과를 검색하는 비용입니다. 이는 기본적으로 아무것도 아닙니다. 따라서 동일한 10M 행에 대한 내 솔루션의 전체 시간은 SAS가 10M 행 + 설정 시간을 통과하는 데 30 초가됩니다. 희망이 도움이됩니다. –

1

을 (목표 테이블의 키 문자열 길이는 다를 수 있음) 열쇠를 통해 반복하고 자신에 의해 일치를하십시오.

data keys; 
length key $10 value $1; 
input key value; 
cards; 
LongString A 
LongOther B 
; 
run; 

proc sort data=keys; 
by key; 
run; 


data data; 
length short_key $10; 
input short_key ; 
cards; 
LongStr 
LongSt 
LongOther 
LongOth 
LongOt 
LongO 
LongSt 
LongOther 
; 
run; 

data match; 
    set data; 
    length key $20 outvalue value $1; 
    drop key value rc; 
    if _N_ = 1 then do; 
     call missing(key, value); 
     declare hash h1(dataset:"work.keys", ordered: 'yes'); 
     declare hiter iter ('h1'); 
     h1.defineKey('key'); 
     h1.defineData('key', 'value'); 
     h1.defineDone(); 
    end; 
    rc = iter.first();/* reset to beginning */ 
    do while (rc = 0);/* loop through the long keys and find a match */ 
     if index(key, trim(short_key)) > 0 then do; 
      outvalue = value; 
      iter.last(); /* leave after match */ 
     end; 
     rc = iter.next(); 
    end; 
run; 
+0

+ 1'd - thankyou –