빠른 빈 좌표(X,Y) 찾기 0 10 1,199

by 쌩크 [Oracle 기초] [2018.02.26 11:57:43]


검색해보니 가장 빠른 빈자리 찾기 질문은 이미 있더라고요.

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개가 모두 찼다면 결과는 없는걸로..

 

어떻게 하면 될까요?

by 우리집아찌 [2018.02.26 12:26:03]

퀴즈란에 올리시고 정답도 좀 ㅋㅋㅋ

 


by 우리집아찌 [2018.02.26 12:47:52]
-- 샘플 데이터는 대충
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

 


by 쌩크 [2018.02.26 13:27:33]

물어보는 입장인데 정답은.. ㅎㅎ

 

샘플 데이터가 좀 걸리는데, 레코드 자체가 일부만 있는 상황이라서 말이죠.

모든 좌표를 다 채워서 타겟으로 만들어둘수가 없지 않을까 싶어요.

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
;

이렇게 해야 올려주신 샘플 데이터랑 같은 형태가 될텐데.. 이건 이중 포괄조인으로 걸려서..


by 우리집아찌 [2018.02.26 13:35:58]

샘플 데이터를 WITH 문으로 만들어주세요.


by 쌩크 [2018.02.26 14:05:49]
with smp as (
         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
  )
  Select * from smp

 


by 우리집아찌 [2018.02.26 14:16:11]
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

 


by 쌩크 [2018.02.26 14:32:45]

오~~ 지금 제가 헤매고 있는 형태보다 훨씬 깔끔하네요.

레벨 X,Y를 한 테이블로 넣고 Left Outer Join 으로 해결하셨군요.

Order by 만 Y, X 로 바꾸면 바로 제가 원하던 답이네요.


by 쌩크 [2018.02.26 14:46:05]

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를 한 쿼리에 넣는것도 해봤는데 그건 왜 안됐었는지 기억이 안나넹..ㅋ

 


by 쌩크 [2018.02.26 16:16:38]
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를 써봐도 별 차이는 없네요.


by 마농 [2018.03.02 10:01:46]
SELECT /*+ LEADING(a) USE_NL(b) */
       a.x, a.y
  FROM (SELECT CEIL(LEVEL / 10) y
             , MOD(LEVEL - 1, 10) + 1 x
          FROM dual CONNECT BY LEVEL <= 100
        ) a
     , smp b
 WHERE a.y = b.y(+)
   AND a.x = b.x(+)
   AND b.x IS NULL
   AND ROWNUM = 1
;

 

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입