검색해보니 가장 빠른 빈자리 찾기 질문은 이미 있더라고요.
level로 포괄 조인 시켜서 비어 있는(Null) 레코드 찾는 형태.
제가 원하는 건 이중배열 인데요.
좌표 같은겁니다.
예를 들어 Y축 10개 X축 10개 한도내에서
가장 빠른 빈좌표를 찾아야 합니다.
Y = 1 부터 X 축 10개를 모두 채우면
다음 Y(2) 의 X(1~10) 을 채우는 거죠.
문제는 중간에 어떤 좌표든 비워질 수 있다는 거에요.
Y (2) : 1, 2, 4
이렇게만 존재한다면 비어있는 좌표 (X, Y) = (1,1)을 찾아와야 겠고요.
Y(1) : 1 ~ 10
Y(2) : 1, 2, 4
이면 (X, Y) = (3, 2) 가 나와야 겠고요.
100개가 모두 찼다면 결과는 없는걸로..
어떻게 하면 될까요?
-- 샘플 데이터는 대충 WITH T AS ( SELECT X , Y , CASE WHEN MOD(Y,3) = 1 OR X <= 3 THEN 'O' ELSE NULL END VAL FROM (SELECT LEVEL AS X FROM DUAL CONNECT BY LEVEL <= 10 ) A , (SELECT LEVEL AS Y FROM DUAL CONNECT BY LEVEL <= 10 ) B ) , T_ARR AS ( SELECT * FROM T PIVOT ( MIN(VAL) FOR Y IN(1 V1, 2 V2, 3 V3, 4 V4, 5 V5, 6 V6, 7 V7, 8 V8, 9 V9, 10 V10)) ) SELECT * FROM (SELECT X , Y , VAL , ROW_NUMBER() OVER(ORDER BY X , Y ) RN FROM T_ARR UNPIVOT INCLUDE NULLS ( VAL FOR Y IN (V1 AS 1, V2 AS 2 ,V3 AS 3, V4 AS 4, V5 AS 5, V6 AS 6 ,V7 AS 7, V8 AS 8 , V9 AS 9, V10 AS 10 ) ) WHERE VAL IS NULL ) WHERE RN = 1
물어보는 입장인데 정답은.. ㅎㅎ
샘플 데이터가 좀 걸리는데, 레코드 자체가 일부만 있는 상황이라서 말이죠.
모든 좌표를 다 채워서 타겟으로 만들어둘수가 없지 않을까 싶어요.
SELECT X , Y
, s.pos_x VAL
FROM (SELECT LEVEL AS X FROM DUAL CONNECT BY LEVEL <= 10 ) A
, (SELECT LEVEL AS Y FROM DUAL CONNECT BY LEVEL <= 10 ) B
, T_TARGET S
where s.pos_y(+) = b.Y
and s.pos_x(+) = a.x
;
이렇게 해야 올려주신 샘플 데이터랑 같은 형태가 될텐데.. 이건 이중 포괄조인으로 걸려서..
WITH T1 AS ( SELECT X , Y FROM (SELECT LEVEL AS X FROM DUAL CONNECT BY LEVEL <= 10 ) A , (SELECT LEVEL AS Y FROM DUAL CONNECT BY LEVEL <= 10 ) B ) , T2 AS ( Select 1 X, 1 Y from Dual union Select 1 X, 2 Y from Dual union Select 3 X, 2 Y From Dual union Select 1 X, 3 Y From Dual union Select 2 X, 3 Y From Dual ) , T_ARR AS ( SELECT T1.X ,T1.Y , T2.X AS val FROM T1 LEFT OUTER JOIN T2 ON T1.X = T2.X AND T1.Y = T2.Y ) SELECT X , Y FROM (SELECT X , Y , VAL FROM T_ARR WHERE VAL IS NULL ORDER BY X , Y ) WHERE ROWNUM <= 1
SELECT X, Y FROM (SELECT X , Y , VAL FROM (SELECT T1.X ,T1.Y, T2.Pos_X AS val FROM (SELECT X , Y FROM (SELECT LEVEL AS X FROM DUAL CONNECT BY LEVEL <= 3 ) A , (SELECT LEVEL AS Y FROM DUAL CONNECT BY LEVEL <= 3 ) B ) T1 LEFT OUTER JOIN T_TARGET T2 ON T1.X = T2.Pos_X AND T1.Y = T2.Pos_Y ) T_ARR WHERE VAL IS NULL ORDER BY Y , X ) WHERE ROWNUM <= 1 ; -- 다 합체 하니 이렇게 되었네요. -- 고맙습니다. -- 레벨X, Y를 한 쿼리에 넣는것도 해봤는데 그건 왜 안됐었는지 기억이 안나넹..ㅋ
Select X, Y from ( Select Y, X, Val, Rank() Over( order by y, x) RK FROM (select t.y, t.x, a.Pos_x as Val from T_TARGET a , (select y, x from (Select level y from dual connect by level <= 3) a , (Select level x from dual connect by level <= 3) b ) t where 1=1 and t.y = a.pos_y(+) and t.x = a.pos_x(+) ) T_ARR Where Val is Null ) Where RK = 1 ;
Rank를 써봐도 별 차이는 없네요.