3가지 조건에 맞는 최대 갯수를 구하고자 합니다. 0 5 668

by 흰다람쥐 [SQL Query] [2021.10.15 22:19:15]


우선 사용중인 db는 오라클 10g 입니다.

한 테이블에서 조건이 여러개이지만 최대 갯수에 맞게 조회를 하고 싶습니다. 

예를 들어 

첫번째 조건은 제가 가지고 있는 품목 중 가장 값비싼 품목 8개를 알고자합니다.

두번째 조건은 채소에서 6개, 과일에서 2개 선택을 하려고 합니다.

그런데 세번째 조건으로 국산은 최대 2개까지 넣을 수 있습니다. 하지만 국산은 채소중에 2개 일 수도 있고, 과일 중에 2개 일 수도 있고, 채소 1개, 과일 1개 일수도 있고, 없을 수도 있습니다.

아래의 표처럼 예시를 만들어 보겠습니다.

품목 종류 가격 원산지
채소 3000 국산
채소 상추 1000 중국
과일 사과 3000 국산
과일 5000 중국
채소 콩나물 3000 국산
채소 4000 중국
채소 버섯 2000 중국
과일 5000 국산
과일 무화과 4000 국산
채소 고구마 6000 국산
채소 완두콩 1000 중국
채소 팽이버섯 7000 국산
채소 깻잎 2000 중국
과일 포도 1000 중국

위의 표는 국산이 비싼 품목이 눈으로 드러나지만 꼭 위의 표와 같진 않을 수 있습니다. 제가 시도한 방법은 select 문을 2개를 사용해 하나의 select 문에서는 채소를 기준으로 6개를 조회하고(row_number()를 사용했습니다) union을 사용해 두번째 select문에서 과일 중 가장 비싼 2개를 조회해(역시 row_number()를 사용했습니다) 8개의 품목을 조회 했는데 국산을 최대 2개를 반영한다는 부분이 도저히 해결이 되지 않습니다.

아마 첫 단추부터 제가 잘못 끼운것 같은데 해결책을 찾지 못하겠습니다. 그래서 고수님들에게 조언을 얻고자 글을 작성했습니다.

많은 조언과 도움 부탁드립니다.

by 우주민 [2021.10.18 11:26:34]
로직 설명
1. 원산지별로 RANK를 설정합니다. 
 - 순서는 비싼순서대로
 - 동일 가격이 있을경우 : 품목명, 종류명 순서로(순서 설정은 사용자의 체크가 필요합니다)
2. 국산일 경우는 최대 2개만 넣을 수 있다는 가정이 있으므로
 - 국산의 제일 비싼 2개만 남겨놓고 국산이 아닐시 모두 남겨둡니다.
3. 남은 항목을 이용해 채소 상위 6개와 과일 상위 2개를 추출합니다.


WITH TEMP1 AS (
SELECT 품목, 종류, 가격, 원산지
,RANK() OVER(PARTITION BY 원산지 ORDER BY 가격 DESC, 품목, 종류) AS RNK
FROM TABLE_이름
)
, TEMP2 AS (
SELECT 품목, 종류, 가격, 원산지
,RANK() OVER(PARTITIN BY 품목 ORDER BY 가격 DESC, 원산지, 종류) AS RNK
FROM TEMP1
WHERE (원산지 = '국산' AND RNK <= 2)
OR 원산지 <> '국산'
)
SELECT 품목, 종류, 가격, 원산지
FROM TEMP2
WHERE (품목 = '채소' AND RNK <= 6)
OR (품목 = '과일' AND RNK <= 2)

현재 DB를 사용하지 못해서 정확한 구문이 아닐 수는 있습니다.
(오류가 나더라도 로직을 참조하면 비슷하게는 나올듯 하네요....)

 


by 흰다람쥐 [2021.10.18 15:47:57]

답변을 달아주셨는데 뒤늦게 확인하여 이제서야 댓글을 달게 되었습니다. 죄송합니다.

다만 여기서 한가지 더 여쭤보고 싶은게 있습니다, 위의 예시대로 말씀을 드리면 국산의 최대 가격이 같은 품목별 종류가 여러개 일 경우, 최대 2개만 반영이 되는데, 원래의 초기 목적인 가장 값비싼 품목들을 가져오려고 하면, 위의 조건대로 진행할 시 제대로 반영이 되지 못하는 경우가 발생하는 것 같습니다. 

한가지 예시로 2번째의 조건으로 만들어 주신 내용에서 말씀을 드리면 채소에서 하위 2개의 가격은 3,000원, 4,000원일 경우 + 과일의 2개 가격은 2,000원, 1,000원 일 경우 과일의 2개 가격을 국산의 최대 가격과 변경을 해야 하는데 최대 가격이 같은 품목의 조회조건의 경우 과일일지 채소일지 명확하게 구분을 하지 못하기 때문에 과일의 2개만 변경이 되지 못하는 것 같습니다. 

혹시 이 부분도 제어가 가능할까요?


by 마농 [2021.10.19 10:12:13]

글쎄요? 말로 풀어쓰거나 간단한 샘플보다는
원하는 바를 명확하게 표현할 수 있는 샘플 자료를 보여 주세요.
원본 대비 결과표 샘플을 보여주세요.
- 여러 경우를 아우를 수 있는 복잡한 조건이 포함된 샘플


by 우주민 [2021.10.19 10:22:57]
 
WITH TEMP1 AS (
SELECT 품목, 종류, 가격, 원산지
,RANK() OVER(PARTITION BY 원산지 ORDER BY 가격 DESC, 원산지, 품목, 종류) AS RNK
FROM TABLE_이름
)
, TEMP2 AS (
SELECT 품목, 종류, 가격, 원산지
,RANK() OVER(PARTITIN BY 품목 ORDER BY 가격 DESC, 원산지, 품목, 종류) AS RNK
FROM TEMP1
WHERE (원산지 = '국산' AND RNK <= 2)
OR 원산지 <> '국산'
)
, TEMP3 AS (
SELECT 품목, 종류, 가격, 원산지
,RANK() OVER(ORDER BY 가격 DESC, 원산지, 품목, 종류) AS RNK
FROM TEMP2
WHERE (품목 = '과일' AND RNK <= 2)
OR 품목 <> '과일'
)
SELECT 품목, 종류, 가격, 원산지
FROM TEMP3
WHERE RNK <= 8
 
과일 항목도 상위 2개만 남기고 날리는 방법은 어떨까요??
딥하게 들어가다보니 생각외로 복잡한 조건들이네요.

 


by 흰다람쥐 [2021.10.19 16:40:19]

답변들 너무 감사합니다. 이게 생각보다 조건들이 너무 복잡하다 보니 머리가 너무 아파서 제가 제대로 설명이나 전달하고 있는지도 모르는 상황이네요,,, 죄송합니다.

예를 들어 샘플 데이터를 만들자면 위의 예제랑 같은 형태로 만들어 보겠습니다. 다만 가격은 제가 헷갈리다 보니 제 임의로 수정해서 다시 올리겠습니다.

품목 종류 가격 원산지
채소 10 국산
채소 5 중국
채소 상추 10 국산
채소 상추 3 중국
채소 콩나물 10 국산
채소 콩나물 7 중국
채소 8 국산
채소 8 중국
채소 버섯 8 국산
채소 버섯 10 중국
채소 토마토 6 중국
채소 완두콩 7 중국
채소 상추 5 중국
채소 깻잎 8 중국
과일 사과 10 국산
과일 사과 4 중국
과일 6 국산
과일 4 중국
과일 포도 6 국산
과일 포도 4 중국
과일 무화과 6 국산
과일 무화과 4 중국

원하는 결과는 채소: 국산무(10), 중국버섯(10), 중국콩(8), 중국깻잎(8), 중국완두콩(7), 중국콩나물(7), 과일 : 국산사과(10), 중국사과(4) -> 마지막 사과는 사과이든 포도이든, 배든 조건이 없고, 맨 상위 국산 무의 경우에도 무든 상추, 콩나물이든 상관없습니다.

위와 같은 상황일 경우 결과 값은 채소에서 국산을 제외한 중국산(품목명이 아닌 가격으로 적겠습니다. 10, 8, 8, 7, 7, 6 이 일반적이며,  과일에서는 같은 가격의 아무거나 2개인 4,4 이렇게 선택이 될텐데, 국산 상위 2개를 자르게 되는경우에는 구분이 없기 떄문에(가장큰 문제입니다....) 가장 낮은 가격의 2개를 가져와서 가장 상위로 비교를 하기가 어렵습니다.

중국산의 가장 하위단의 품목 2개를 국산의 품목들과 비교하여 최상의 8개 가격을 가진 품목들로 가져올 수 있을까요?

선입견을 가지시진 않겠지만, 제가 생각한 내용은 중국산을 품목별 조건으로 검색해 와서 다시 그것들로만 ROW_NUMBER를 써서 순위를 매긴다음 하위단 2개를 국산을 가져오는 임시테이블로 비교를 하려고 하나 생각보다 쉽지 않습니다.

고수님들의 소중한 조언을 부탁드립니다. 

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