* 출처 : http://cafe.daum.net/statsas/3F8j/162
다른 방법이 있으시면 알려주시면 감사하겠습니다.
/* 보통 오라클에서 FIRST와 LAST의 기능으로는 상관 서브쿼리를 사용하지만,
SAS에서는 서브쿼리 사용시 HASH 조인으로 조인이 안되고, 필터를 사용하는듯 합니다.
아래의 몇가지 방법을 나열해 보았습니다.
방법이 문제가 아니라 속도가 문제인데, 속도 테스트는 아직 못해봤네요..
홍길동 B 7
홍길동 B 7
이렇게 다른 변수없이 MAX값에 중복발생할경우 처리가 문제가 되겠네요..
보통은 SERIAL변수가 있어서 중복제거를 할텐데, 아래에서는 DISTINCT로 중복을 제거하였습니다. */
DATA BACK;
INPUT NAME $ TYPE $ SEQ;
CARDS;
백승민 A 4
백승민 A 1
홍길동 A 2
신승훈 A 3
홍길동 A 3
백승민 A 2
백승민 B 4
백승민 B 5
홍길동 A 1
홍길동 A 4
홍길동 A 5
홍길동 B 3
백승민 A 3
홍길동 B 4
홍길동 B 5
홍길동 B 6
신승훈 A 1
신승훈 A 2
백승민 B 3
신승훈 A 4
백승민 B 1
백승민 B 2
홍길동 B 1
홍길동 B 2
홍길동 B 7
홍길동 B 7
;
RUN;
* 방법1 : LAST;
PROC SORT DATA=BACK OUT=BACK11;
BY NAME TYPE SEQ;
RUN;
DATA BACK12;
SET BACK11;
BY NAME TYPE SEQ;
IF LAST.TYPE;
run;
PROC PRINT;RUN;
* 방법2 : NODUPKEY;
PROC SORT DATA=BACK OUT=BACK21;
BY NAME TYPE DESCENDING SEQ;
RUN;
PROC SORT DATA=BACK21 OUT=BACK22 NODUPKEY;
BY NAME TYPE;
RUN;
PROC PRINT;RUN;
* 방법3(상관SUB-쿼리) : PROC SQL의 MAX;
* 만약 KEY값에 중복 존재시 완전제거 못함- 다른 기준을 통하여 중복제거(현재는 DISTINCT로 중복제거);
* HASH JOIN을 안하고 필터를 사용함으로 속도문제발생;
PROC SQL;
CREATE TABLE BACK31 AS
SELECT DISTINCT A.*
FROM BACK A
WHERE A.SEQ = ( SELECT MAX(B.SEQ)
FROM BACK B
WHERE A.NAME = B.NAME
AND A.TYPE = B.TYPE );
SELECT * FROM BACK31;
QUIT;
* 방법4(JOIN) : PROC SQL의 MAX;
* 만약 KEY값에 중복 존재시 완전제거 못함- 다른 기준을 통하여 중복제거(현재는 DISTINCT로 중복제거);
PROC SQL;
CREATE TABLE BACK41 AS
SELECT DISTINCT A.*
FROM BACK A,
( SELECT NAME,
TYPE,
MAX(B.SEQ) AS SEQ
FROM BACK B
GROUP BY NAME,TYPE) B
WHERE A.NAME = B.NAME
AND A.TYPE = B.TYPE
AND A.SEQ = B.SEQ;
SELECT * FROM BACK41;
QUIT;
* 방법5(HAVING) : PROC SQL의 MAX;
* 만약 KEY값에 중복 존재시 완전제거 못함- 다른 기준을 통하여 중복제거(현재는 DISTINCT로 중복제거);
PROC SQL;
CREATE TABLE BACK51 AS
SELECT DISTINCT *
FROM BACK A
GROUP BY NAME,TYPE
HAVING A.SEQ = MAX(A.SEQ);
SELECT * FROM BACK51;
QUIT;
* 방법6(MONOTONIC);
* SAS의 서브쿼리에서는 ORDER BY가 실행이 안되는듯 합니다. 그리고 MONOTONIC은 데이터를 읽은 순서대로 순위를 부여하는듯 합니다.;
* MONOTONIC의 기능이 제한적이라서 거의 사용될일은 없는듯 합니다.;
PROC SQL;
CREATE TABLE BACK61 AS
SELECT *
FROM BACK
ORDER BY NAME,TYPE,SEQ;
CREATE TABLE BACK62(DROP=SERIAL) AS
SELECT A.*
FROM ( SELECT *,MONOTONIC() AS SERIAL
FROM BACK61 AS K
GROUP BY NAME,TYPE
HAVING SERIAL=MAX(SERIAL) ) AS A;
SELECT * FROM BACK62;
QUIT;
* 방법7(INTERSECT);
PROC SQL;
SELECT *
FROM BACK
INTERSECT
SELECT NAME,
TYPE,
MAX(B.SEQ) AS SEQ
FROM BACK B
GROUP BY NAME,TYPE;
QUIT;
[오라클 참고] : http://cafe.daum.net/statsas/3F8l/6
Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.