쿼리 답변을 부탁드려요~ 0 6 810

by 산달 [SQL Query] [2016.06.15 13:53:53]


여러개의 상품이 있습니다.
여러 상품중에서 가격이 제일 높은 순으로 상품을 5개를 추출할려고 합니다.(상품종류는 상관없음)
이것은 RANK함수를 이용하여 추출하면 되는데..
문제는 가격이 제일 높은 순으로 상품을 5개를 추출할때 꼭 2가지 상품(예, A, Z)도 가격이 제일 높은 순으로 항상
포함이 되어야 한다는 거죠. 설령 A, Z 상품이 5개를 추출한 상품의 가격보다 작더라도 A, Z상품들 중에서 제일 높은 상품
2개는 포함이 되어야 하며, A, Z 상품이 가격이 높아 5개에 해당될 수 도 있습니다.
따라서 A, Z상품은 무조건 각 1개씩은 포함되어야 합니다. 아래의 결과는 예 입니다.

상품 가격
A     8
B     10
C     12
D     10
Z     7
A     5
Z     3
B     15
B     12
C     8
Z     5

위 값 정렬은 B,C,B,B,D,A,C,Z,A,Z,Z....
결과(5개) : B,C,B,B,D -> B,C,B,A,Z (최종 결과)
위 처럼 A,Z 상품의 제일 높은 가격이 포함되어야 합니다.
정렬을 했을 경우 A, Z 상품들이 5번째에 포함되면 되는데 그렇지 않을 경우 A, Z를 포함을 시켜야하는데
쿼리로 가능한지가 궁금합니다.

by jkson [2016.06.15 14:35:09]

A, Z가 아닌 것으로 3개 뽑고 A, Z인 것으로 2개 뽑아서 UNION 하면 안 되나요?


by 우리집아찌 [2016.06.16 09:25:33]

UINON ALL 쓰는게 제일 간단할듯합니다.


by 랑에1 [2016.06.15 15:22:40]

WITH T AS(
SELECT 'A' a,     8 b FROM dual UNION ALL 
SELECT 'B',     10 FROM dual UNION ALL 
SELECT 'C',     12 FROM dual UNION ALL 
SELECT 'D',     10 FROM dual UNION ALL 
SELECT 'Z',     7 FROM dual UNION ALL 
SELECT 'A',    5 FROM dual UNION ALL 
SELECT 'Z',     3 FROM dual UNION ALL 
SELECT 'B',     15 FROM dual UNION ALL 
SELECT 'B',     12 FROM dual UNION ALL 
SELECT 'C',     8 FROM dual UNION ALL 
SELECT 'Z',     5 FROM dual  
)

SELECT a, b
FROM 
(
SELECT T.*
, CASE WHEN a IN ('A', 'Z') THEN (ROW_NUMBER() OVER(PARTITION BY a ORDER BY b DESC)) + 2 ELSE ROW_NUMBER() OVER(ORDER BY b DESC) END rn
FROM T
)
WHERE rn <= 3

union 쓰시면 될 것 같으나 구지 안쓰고 억지로 한다면 이정도로 하면 되려나요?
정렬은 좀 다듬고요

 


by 마농 [2016.06.16 15:52:37]

A, Z 가 상위 5개를 모두 차지한다면?

예) A, A, Z, A, A, B, C  ===> 결과는? A, A, Z, A, A 이렇게 나올 수도 있겠네요?


by jkson [2016.06.16 18:24:26]

A, Z로만 5개될 수도 있다는 멘트가 있었군요~ 이게 정답이네요~ 역시 꼼꼼하시네요-0-


by 마농 [2016.06.16 16:26:03]
WITH t AS
(
SELECT 'A' cd, 8 amt FROM dual
UNION ALL SELECT 'B', 10 FROM dual
UNION ALL SELECT 'C', 12 FROM dual
UNION ALL SELECT 'D', 10 FROM dual
UNION ALL SELECT 'Z',  7 FROM dual
UNION ALL SELECT 'A',  5 FROM dual
UNION ALL SELECT 'Z',  3 FROM dual
UNION ALL SELECT 'B', 15 FROM dual
UNION ALL SELECT 'B', 12 FROM dual
UNION ALL SELECT 'C',  8 FROM dual
UNION ALL SELECT 'Z',  5 FROM dual
--UNION ALL SELECT 'Z', 16 FROM dual
--UNION ALL SELECT 'Z', 16 FROM dual
--UNION ALL SELECT 'Z', 16 FROM dual
--UNION ALL SELECT 'Z', 16 FROM dual
--UNION ALL SELECT 'Z', 16 FROM dual
)
SELECT cd, amt
  FROM (SELECT cd, amt
          FROM (SELECT cd, amt
                     , ROW_NUMBER() OVER(ORDER BY amt DESC, cd) rn1
                     , CASE WHEN cd IN ('A', 'Z')
                             AND ROW_NUMBER() OVER(PARTITION BY cd ORDER BY amt DESC) = 1
                            THEN 1 ELSE 2 END rn2
                  FROM t
                )
         WHERE rn1 <= 5 OR rn2 = 1
         ORDER BY rn2, rn1
        )
 WHERE ROWNUM <= 5
 ORDER BY amt DESC, cd
;

 

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