3번 이상 연속되는 수 찾기와 몇개가 있는지 2 13 2,164

by 허승호 연속수 [2015.08.06 16:42:25]


안녕하세요.

아래에는 여러개의 숫자가 보입니다.

출력하고자 하는 것은 3개이상 연속된 수의 여부를 파악해서 출력해야 하는 것입니다.

단 집계함수를 써서 해결해야 하구요.

데이터는 아래와 같습니다.

WITH RS AS (
SELECT 201  AS N FROM DUAL  UNION ALL
SELECT 202 FROM DUAL UNION ALL 
SELECT 204 FROM DUAL UNION ALL 
SELECT 205 FROM DUAL UNION ALL 
SELECT 206 FROM DUAL UNION ALL 
SELECT 209 FROM DUAL UNION ALL 
SELECT 210 FROM DUAL UNION ALL 
SELECT 215 FROM DUAL UNION ALL 
SELECT 216 FROM DUAL UNION ALL 
SELECT 217 FROM DUAL 
)
SELECT COUNT(*) FROM RS GROUP BY 1

결과는 아래와 같습니다.

3개 이상 연속수 여부  
존재함  

 

by jkson [2015.08.06 16:53:26]
WITH RS AS (
SELECT 201  AS N FROM DUAL  UNION ALL
SELECT 202 FROM DUAL UNION ALL
SELECT 204 FROM DUAL UNION ALL
SELECT 205 FROM DUAL UNION ALL
SELECT 206 FROM DUAL UNION ALL
SELECT 209 FROM DUAL UNION ALL
SELECT 210 FROM DUAL UNION ALL
SELECT 215 FROM DUAL UNION ALL
SELECT 216 FROM DUAL UNION ALL
SELECT 217 FROM DUAL 
)
SELECT DECODE (NVL (MAX (cnt), 0), 0, '존재하지않음', '존재함') as "3개이상연속수여부"
     , COUNT(1) AS "건수" 
  FROM (SELECT COUNT (1) cnt
          FROM (SELECT ROW_NUMBER () OVER (ORDER BY n) rn, n
                  FROM rs)
        GROUP BY n - rn)
 WHERE cnt >= 3
 

 


by 허승호 [2015.08.06 17:18:35]

//jkson 님 답변 감사 드립니다.

제 뜻이 전달이 잘못되었나 봅니다.  

가급적이면 인라인뷰를 안쓰는 방향으로 하는 질문이였구요 

아래처럼 공식이나 집계함수 그런걸 이용하여 써서 구하는게 의도 하는바였습니다.

SELECT (CASE (집계함수연산) = TRUE WHEN '존재함' ENDFROM RS GROUP BY 1


by jkson [2015.08.06 17:53:56]
SELECT NVL(MAX(VAL),'존재하지않음') AS "3개이상연속수여부"
  FROM (
       SELECT CASE WHEN (LAG(N) OVER(ORDER BY N) + LEAD(N) OVER(ORDER BY N)) / 2 = N THEN '존재함' ELSE NULL END VAL
         FROM rs
       )

가공한 데이터를 가지고 한번 걸러줘야해서

인라인뷰를 안 쓰고 만들기는 까다로울 것 같은데

굳이 안 쓰시려는 이유가 있나요?


by 창조의날개 [2015.08.06 18:07:22]

SELECT CASE WHEN (SUM(CASE WHEN COUNT(*) >= 3 THEN 1 ELSE 0 END)) > 0
            THEN '존재함'
            ELSE '존재하지않음'
       END AS "3개 이상 연속수 여부"
FROM (
    SELECT N, N-ROW_NUMBER() OVER (ORDER BY N) GP
    FROM RS
)
GROUP BY GP
;

SELECT CASE WHEN (SUM(CASE WHEN COUNT(*) >= 3 THEN 1 ELSE 0 END)) > 0
            THEN '존재함'
            ELSE '존재하지않음'
       END AS "3개 이상 연속수 여부"
FROM (SELECT N FROM RS ORDER BY N)
GROUP BY N-ROWNUM
;

 

-- N기준으로 이미 ORDER BY 가 되었다면...

SELECT CASE WHEN (SUM(CASE WHEN COUNT(*) >= 3 THEN 1 ELSE 0 END)) > 0
            THEN '존재함'
            ELSE '존재하지않음'
       END AS "3개 이상 연속수 여부"
FROM RS
GROUP BY N-ROWNUM
;

 


by 마농 [2015.08.07 08:58:57]
SELECT NVL(MIN(MIN('존재함')), '존재안함') rs
  FROM rs
 GROUP BY n - ROWNUM
HAVING COUNT(*) >= 3
;

 


by jkson [2015.08.07 09:04:57]

마농님 rs에 n 데이터가 정렬 되어있다는 가정하에서만 쓸 수 있는 거죠? 어제 많이 생각해봤는데 데이터가 정렬이 안 되어있는 상태라면 인라인뷰를 안 쓰고는 어려울 것 같은데 방법이 있을까요?


by 마농 [2015.08.07 09:17:25]

네. 당연한 얘기지요...

정렬도 필요한 문제이며.. 앞뒤 데이터간의 연관관계를 알아야 하는 문제입니다.

이런 문제는 보통 분석함수를 이용할수밖에 없는데요.

그나마 위 방법은 분석함수를 이용하지 않는 방법입니다.


by jkson [2015.08.07 09:35:29]

답변 감사합니다. 인라인뷰 안쓰고 해보려고 아무리 머리 굴려봐도 답이 안 나와서요^^;


by 허승호 [2015.08.07 09:54:10]

//jkson님, 마농님 답변 주셔서 정말 감사합니다. 

다들 문제 해결능력이 탁월하십니다.^^ 좋은 주말 되십시요.


by 고슴도치 [2015.08.07 10:35:47]

참고 하겠습니다, 정말 대단합니다.

[oracle 집계함수 활용법 (20150807)]


by 마농 [2015.08.07 14:19:21]
SELECT CASE WHEN MAX(LEVEL) >= 3 THEN '존재함' ELSE '존재암함' END rs
  FROM rs
 WHERE CONNECT_BY_ISLEAF = 1
 CONNECT BY PRIOR n + 1 = n
;

 

 


by jkson [2015.08.07 16:00:01]

컥!!!! 대단하십니다. 와~ 생각치도 못했네요. 또 배웁니다. 감사합니다ㅋ


by 마농 [2015.08.07 16:03:57]
-- 약간의 튜닝을...
SELECT NVL(MIN('존재함'), '존재암함') rs
  FROM rs
 WHERE CONNECT_BY_ISLEAF = 1
   AND LEVEL = 3
   AND ROWNUM = 1
 CONNECT BY PRIOR n + 1 = n
   AND LEVEL <= 3
;

 

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