[오라클10g][토드]SQL질문이요.. 0 12 4,149

by 이상민 오라클 토드 sql [2011.12.28 15:46:09]



법정동코드 구분코드 백분율
2820010200 101903  14.9176435882768
2820010200  120102 82.0846210234295
2820010200  120103 2.99773538829369


위와 같은 자료에서
최소값을 최대값에 합치고 나머지 중간값들은 그대로 보여주게 하려면
어떻게 쿼리를 하면 될까요?


MIN MAX로 최소값과 최대값을 구해서 더하는것 까지는 했는데
중간 값들과 함께 보여주기가 힘드네요..ㅠㅠ


원하는 결과는 아래와 같습니다
법정동코드 구분코드 백분율
2820010200 101903  14.9176435882768<-중간값
2820010200  120102 85.08235641172319(최소값+최대값)
by 마농 [2011.12.28 16:40:47]
per 값을 구할 때 sum 을 하셨는데? sw_code 값이 중복이 가능한건가요?
중복이 가능하다면? 위에 count 는 COUNT(DISTINCT sw_code) 로 구해야 맞습니다.
중복이 안된다면? group by sum 은 무의미한 소모적인 작업입니다.

2건 이하는 조회대상이 아닌가요?
위와 같이 하면 2건짜리 자료는 아예 조회가 안됩니다.

by 이상민 [2012.01.02 11:48:41]
위에 붙여놓은 쿼리는 단순하게 하나의 bjd_cde에 sw_code가 3개 이상되는 항목에서 최대값과 최소값을 더하는 쿼리입니다.

by 이상민 [2012.01.02 11:53:02]
참고로 말씀드리면 하나의 법정동 코드에 여러개의 sw_code별로 per값을 구하는 것이기 때문에 sw_code는 중복되면 안됩니다.
2건 이하는 조회 하는데요 그 부분은 해결했기 때문에 질문사항에 넣지 않았습니다.
2건 이하 조회 부분과 3건 이상 부분의 쿼리를 나눠서 부른 다음에 데이터 테이블로 합쳐서 보여주려 합니다

by 이상민 [2012.01.02 11:57:55]
아래의 쿼리는 2건이하의 자료중 같은 bjd_cde중 per값이 3이하면 감추고 97이상은 100으로 만드는 쿼리입니다

select SEQ_NO,EXAMIN_YEAR,BJD_CDE,SW_CODE,SW_NAME,MW_NAME,MW_CODE,LW_NAME,LW_CODE
,case when PER >=97 then 100 else PER end as AREA_PER
from (
select SEQ_NO,EXAMIN_YEAR,AA.BJD_CDE
,SW_CODE,SW_NAME,MW_NAME,MW_CODE,LW_NAME,LW_CODE,SUM(BJD_POSSESN_AREA/BJD_TOT_AREA)*100 as PER
from LC_BJD_WRSSM_AREA AA,
(
SELECT BJD_CDE,COUNT(BJD_CDE)
FROM LC_BJD_WRSSM_AREA
WHERE EXAMIN_YEAR = 2010
GROUP BY BJD_CDE
HAVING COUNT(BJD_CDE)<3
) BB
where
--SW_CODE ='120102'
--AND
EXAMIN_YEAR = 2010
AND AA.BJD_CDE = BB.BJD_CDE
group by SEQ_NO,EXAMIN_YEAR,AA.BJD_CDE
,SW_CODE,SW_NAME,MW_NAME,MW_CODE,LW_NAME,LW_CODE
having (SUM(BJD_POSSESN_AREA/BJD_TOT_AREA)*100)> 3
)
ORDER BY BJD_CDE

by 마농 [2012.01.02 13:14:35]
제 질문은 결과에 중복이 존재하는지가 아니라 원본에 중복이 존재하는지 입니다.
하나의 법정동 코드에 중복되는 sw_code 가 존재하나요?
중복이 되지 않는다면 Group By Sum 은 불필요한 코드입니다.

by 이상민 [2012.01.03 16:13:18]
아 당연히 중복 됩니다 그래서 sum을 하는거구요

by 마농 [2012.01.03 16:18:05]
그러면 위에 카운트가 잘못 되었네요?
-- COUNT(BJD_CDE)
COUNT(DISTINCT sw_code) -- 이런식이어야 하겠죠?
위 아래 소스코드가 전혀 상반되니 섯불리 답글을 달 수가 없엇네요.


by 이상민 [2012.01.03 16:19:46]
본문에 적어놓은 쿼리는 단순히 하나의 법정동안에 sw_code가 3개 이상인 값들의 최대값과 최소값을 구해서 더하는 거구요 댓글에 달아놓은 쿼리는 2건이하의 값들만 보여주는 겁니다

by 이상민 [2012.01.03 16:21:45]
select rownum as NO,EXAMIN_YEAR,BJD_CDE,SW_CODE,SW_NAME,MW_NAME,MW_CODE,LW_NAME,LW_CODE
,case when PER >=97 then 100 else PER end as AREA_PER
from (
select EXAMIN_YEAR,BJD_CDE
,SW_CODE,SW_NAME,MW_NAME,MW_CODE,LW_NAME,LW_CODE,SUM(BJD_POSSESN_AREA/BJD_TOT_AREA)*100 as PER
from LC_BJD_WRSSM_AREA
where
EXAMIN_YEAR = 2010
group by EXAMIN_YEAR,BJD_CDE
,SW_CODE,SW_NAME,MW_NAME,MW_CODE,LW_NAME,LW_CODE
having (SUM(BJD_POSSESN_AREA/BJD_TOT_AREA)*100)> 3
)
ORDER BY BJD_CDE

이 쿼리로 돌리면 하나의 법정동에 sw_code가 두개 이하인 값은 해결되지만 3개 이상되는 것들이 문제가 생기더라구요
그 문제는 예를 들어 82,16,2 이렇게 나오면 2값을 가지는 로우는 없어지고 82,16인 값만 보여지는데요 두개를 합했을때 100이 되지 않기 때문에 82가 84로 변경되는 쿼리를 만들고 싶은겁니다

by 마농 [2012.01.03 16:57:02]
단순히 2건, 3건이 맞다고 계속 하시는데
건수구하는 방식이 틀렸습니다.
중복 건수는 한번만 카운트 하셔야 맞죠...

그리고 2건 3건 나눠서 쿼리하실 필요 없습니다.
될수있으면 한번에 하시는게 좋습니다.

그리고 질문내용에는 bjd_cde, sw_code 두개 항목만 나오는데
쿼리에는 질문내용에 없는 항목들이 조회되고 있는데...
이 값들이 나와야 하는 값인지?
항목들의 의미가 무었인지?
법정동 코드 내에서 중복여부 등등... 설명이 없네요.

by 마농 [2012.01.03 16:58:19]
WITH lc_bjd_wrssm_area AS
(
SELECT '2010' examin_year, '2820010200' bjd_cde, '101903' sw_code, 14.9176435882768 bjd_possesn_area, 100 bjd_tot_area FROM dual
UNION ALL SELECT '2010', '2820010200', '120102', 82.0846210234295, 100 FROM dual
UNION ALL SELECT '2010', '2820010200', '120103', 2.99773538829369, 100 FROM dual
UNION ALL SELECT '2010', 'xxxxxxxxxx', '111111', 97, 100 FROM dual
UNION ALL SELECT '2010', 'xxxxxxxxxx', '222222', 2, 100 FROM dual
UNION ALL SELECT '2010', 'xxxxxxxxxx', '222222', 1, 100 FROM dual
UNION ALL SELECT '2010', 'yyyyyyyyyy', '333333', 70, 100 FROM dual
UNION ALL SELECT '2010', 'yyyyyyyyyy', '444444', 30, 100 FROM dual
UNION ALL SELECT '2010', 'zzzzzzzzzz', '999999', 100, 100 FROM dual
)
SELECT bjd_cde, sw_code--, per
, CASE WHEN cnt >= 3 AND rn = 1 THEN per + min_per
WHEN cnt < 3 AND per >= 97 THEN 100
ELSE per END per
FROM
(
SELECT bjd_cde, sw_code, per
, COUNT(*) OVER(PARTITION BY bjd_cde) cnt
, MIN(per) OVER(PARTITION BY bjd_cde) min_per
, ROW_NUMBER() OVER(PARTITION BY bjd_cde ORDER BY per DESC) rn
FROM
(
SELECT bjd_cde, sw_code
, SUM(bjd_possesn_area/bjd_tot_area)*100 per
FROM lc_bjd_wrssm_area
WHERE examin_year = 2010
GROUP BY bjd_cde, sw_code
)
)
WHERE per > CASE WHEN cnt >= 3 THEN min_per ELSE 3 END
;

by 손님 [2012.01.04 14:09:58]
마농님 처럼 될려면 얼마나 공부를 해야될까요..

쿼리만 딱 보구 이해하시는게.... 전 이상민님이 만들어놓을것을 임의로 하나만들어서

테스트해본결과 마농님말이 맞는지를 알앗는데... 으음..

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