이 짧은 쿼리 해석을 못하겠어요... 0 10 1,713

by 송새롬 [2013.06.19 15:30:56]


초보인 제가 쿼리 작성을 하려 하는데요, 쿼리를 받긴 했는데 몇가지 궁금 사항이 있어서요ㅠㅠ
 (SELECT 
   TO_CHAR (TO_DATE ('20130501','YYYY-MM-DD')+LEVEL- 1, 'YYYYMMDD') AS DAY
   ,ceil(
   (
   to_number(substrb(TO_CHAR (TO_DATE ('20130501','YYYY-MM-DD')+LEVEL- 1, 'YYYYMMDD'), -2, 2)) 
   + 7 
   - to_number(TO_CHAR(TO_DATE(TO_CHAR (TO_DATE ('20130501','YYYY-MM-DD')+LEVEL- 1, 'YYYYMMDD'),'YYYYMMDD'),'D'))
   )/7 
   )|| ' 주차' WEEK
  FROM DUAL
  CONNECT BY TO_DATE('20130501', 'YYYY-MM-DD') + LEVEL - 1 <= TO_DATE('20130530', 'YYYY-MM-DD')
  UNION ALL
  SELECT '단위 합계', '' FROM DUAL
  ) DAY 
1) +LEVEL- 1 은 정확히 무슨 역할을 하나요?

 2) +LEVEL- 1, 'YYYYMMDD'), -2, 2)) 에서 -2, 2 는 무슨 역할을 하나요?

  3)
 

(
                      to_number(substrb(TO_CHAR (TO_DATE ('20130501','YYYY-MM-DD')+LEVEL- 1, 'YYYYMMDD'), -2, 2)) 
                     + 7 
                     - to_number(TO_CHAR(TO_DATE(TO_CHAR (TO_DATE ('20130501','YYYY-MM-DD')+LEVEL- 1, 'YYYYMMDD'),'YYYYMMDD'),'D'))
                     )/7 
                     )|| ' 주차' WEEK
             FROM DUAL
             CONNECT BY TO_DATE('20130501', 'YYYY-MM-DD') + LEVEL - 1 <= TO_DATE('20130530', 'YYYY-MM-DD')
             UNION ALL
             SELECT '단위 합계', '' FROM DUAL
            ) DAY

 
이 부분 해석해 주시면 감사할께요 ㅠㅠ 질문이 많아서 죄송합니다 ㅡ.ㅠㅠㅠ
by 아발란체 [2013.06.19 16:06:21]
1번 질문에서 level은 CONNECT BY로 인해 발생하는 레벨을 표시하는 것입니다.
해당 구문이 없으면 레벨을 쓸 수 없습니다.
위는 CONNECT BY 를 통해 데이타를 병렬로 증가 시켜 순차적인 날짜 증가 데이타를 만든 것인데

SELECT LEVEL FROM DUAL CONNECT BY LEVEL <= 10
먼저 이거 실행 해보시면 대략 이해하실거에요.

"계층"이라고 검색하시면 강좌나 마농님이 올리신 아주 보물 같은 글들이 많습니다.
(이해하고 나면 뼈와 살이 되는)
이걸 먼저 이해하셔야 해당 용도를 정확히 아실 수 있으리라 생각합니다.

2번째 질문은 서브스트링으로 문자열 짜르는 것인데
SUBSTRB처럼 뒤에 B가 붙어 바이트 단위로 짜를 수 있는 것이고
-2와, 2가 SUBSTRB 인자 값입니다.

-2면
'안녕하세'에서 밑줄친 "요"를 말하며 뒤에서 부터 2BYTE 되는 지점부터 자르라는 것입니다.

2는
"요" 라는 글자부터 2BYTE를 가지로 오라는 것입니다.

값을 -4, 2 하면 "안녕하세요"에서 "세"를 가지고 옵니다.
-2, 2 하면 "요"를 가지고 옵니다.
-6, 2 하면 "하"를 가지고 옵니다.
-6, 4 하면 "하세"를 가지고 옵니다.


이건 좀 다른 얘기가 될 수 있지만
전 오라클 한글셋을 어떻게 하고 설치했나 위처럼 하면 정상적인 결과가 안나옵니다.
한글이 3BYTE로 잡혀 있습니다. ㅎㅎ
즉 위 질의는 오라클 환경이 바뀌면 범용적으로 쓸 수 있는 질의는 아닙니다.
기억이 잘 안나는데... 한글 1자가 몇 바이트로 잡혔는지 확인하는 질의도 있습니다.
그걸 대입해야 보다 범용적인 질의가 될듯 싶습니다.

by 우리집아찌 [2013.06.19 16:20:46]
 
-- 5월1일 부터 5월30일까지 각 일자별 주차를 구하는건가보네요..
-- 마농님꺼 카피엔 페이스트로 만든 잔재주..
SELECT dt 
 , CEIL((dt + 1 - TRUNC(TRUNC(dt, 'mm'), 'iw') + 1) / 7) w 
 FROM (SELECT TO_DATE ('20130501','YYYY-MM-DD') + LEVEL - 1 dt 
  FROM dual 
 CONNECT BY LEVEL <= TO_DATE ('20130530','YYYY-MM-DD') - TO_DATE ('20130501','YYYY-MM-DD') + 1 ) 
; 

by 마농 [2013.06.20 09:19:34]
전 : CEIL((dt + 1 - TRUNC(TRUNC(dt, 'mm'), 'iw') + 1) / 7) w
후 : CEIL((dt - TRUNC(TRUNC(dt, 'mm'), 'd') + 1) / 7) w

by 신이만든짝퉁 [2013.06.19 16:50:24]
3번을 풀어쓰면 대충 이런 뜻입니다. (첫 번째 로우를 예로 듭니다.)
(+ level 은 1부터 30까지 순차적으로 증가하는 값입니다. 윗분들이 설명하셨으니 생략합니다.
여기서는 첫번째 로우를 예로 들었으므로 + LEVEL - 1은 + 1 - 1 하여 값이 0 입니다 )

to_number(substrb(TO_CHAR (TO_DATE ('20130501','YYYY-MM-DD')+LEVEL- 1, 'YYYYMMDD'), -2, 2)) + 7
--> '20130501'에서 '01'만 떼어내어 숫자로 변환 한 뒤 7을 더함(결과는 8)

to_number(TO_CHAR(TO_DATE(TO_CHAR (TO_DATE ('20130501','YYYY-MM-DD')+LEVEL- 1, 'YYYYMMDD'),'YYYYMMDD'),'D'))
--> '20130501'날짜가 요일로 변환 시 몇번 째인가 반환(결과는 4, 일요일 1 ~ 토요일 7)

 to_number(substrb(TO_CHAR (TO_DATE ('20130501','YYYY-MM-DD')+LEVEL- 1, 'YYYYMMDD'), -2, 2))
  + 7  - to_number(TO_CHAR(TO_DATE(TO_CHAR (TO_DATE ('20130501','YYYY-MM-DD')+LEVEL- 1, 'YYYYMMDD'),'YYYYMMDD'),'D'))
--> 위 두 결과를 빼기함( 결과는  8 - 4 = 4)


 (to_number(substrb(TO_CHAR (TO_DATE ('20130501','YYYY-MM-DD')+LEVEL- 1, 'YYYYMMDD'), -2, 2))
  + 7 - to_number(TO_CHAR(TO_DATE(TO_CHAR (TO_DATE ('20130501','YYYY-MM-DD')+LEVEL- 1, 'YYYYMMDD'),'YYYYMMDD'),'D')))/7  
--> 위 결과를 7로 나눔( 결과는  (8 - 4) / 7  = 0.571428571428571 )

ceil(
  (
  to_number(substrb(TO_CHAR (TO_DATE ('20130501','YYYY-MM-DD')+LEVEL- 1, 'YYYYMMDD'), -2, 2))
  + 7
  - to_number(TO_CHAR(TO_DATE(TO_CHAR (TO_DATE ('20130501','YYYY-MM-DD')+LEVEL- 1, 'YYYYMMDD'),'YYYYMMDD'),'D'))
  )/7
-->  위 결과를 ceil 함수에 넣음 ( 결과는 ceil( 0.571428571428571 ) = 1 )

ceil(
  (
  to_number(substrb(TO_CHAR (TO_DATE ('20130501','YYYY-MM-DD')+LEVEL- 1, 'YYYYMMDD'), -2, 2))
  + 7
  - to_number(TO_CHAR(TO_DATE(TO_CHAR (TO_DATE ('20130501','YYYY-MM-DD')+LEVEL- 1, 'YYYYMMDD'),'YYYYMMDD'),'D'))
  )/7
  )|| ' 주차'
--> 위 결과에 ' 주차'를 붙여 표시( 결과는 1 주차 ) 


CONNECT BY TO_DATE('20130501', 'YYYY-MM-DD') + LEVEL - 1 <= TO_DATE('20130530', 'YYYY-MM-DD')
--> 위 작업을 20130501 부터 20130530 까지 30번 반복함


 UNION ALL
 SELECT '단위 합계', '' FROM DUAL
--> 단순히 맨 마지막에  단위 합계 라는 값을 붙여 줌

by 디케이 [2013.06.19 17:29:15]
 
--같은결과 다른방식으로 주차계산.. ㅎㄷㄷ
 SELECT dt
  , 1+SUM(decode(to_char(dt, 'd'), 1, 1,0)) OVER (PARTITION BY TRUNC(dt, 'mm') ORDER BY dt) || '주차'
 FROM ( 
   SELECT TO_DATE ('20130501','YYYY-MM-DD') + LEVEL - 1 dt 
   FROM dual 
 CONNECT BY LEVEL <= TO_DATE ('20130530','YYYY-MM-DD') - TO_DATE ('20130501','YYYY-MM-DD') + 1 
   )
 ;

by 우리집아찌 [2013.06.19 17:35:54]
놀라운데요.. TO_CHAR(date,'d')  를 이렇게 응용할수있군요...

by 신이만든짝퉁 [2013.06.19 17:44:05]
대단하시군요~~ 저도 배우고 갑니다. ^^

by 디케이 [2013.06.20 08:26:28]
음. 다시보니 오류가 있네요..
일요일부터 시작하는 경우(20130901~) 바로 2주차로 되어버리네요. ㅎㅎ
조건추가해주기보단 아찌님 쿼리간결하네요..

by 마농 [2013.06.20 09:11:31]
날짜포멧 'd' 와 분석함수를 사용하시려면 다음과 같이...
DENSE_RANK() OVER(ORDER BY TRUNC(dt, 'd'))

by 디케이 [2013.06.20 10:44:42]
오오 역시 마농님..
댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입