subquery와 Profit 비교 계산하는 법에 대해서 질문드립니다. 0 7 451

by 머루원해 [SQL Query] [2018.11.06 12:54:17]


20181105_164929.png (23,767Bytes)
20181105_215132.png (64,117Bytes)

SQL 문제는

Eastwood의 모든 영화가 흥행한 것은 아니었다. 1980년에서 2000년 사이에 개봉되고, 평균 이하의 수익을 올린 영화들의 목록을 반환하는 서브쿼리를 작성해라. 영화 제목, 개봉 연도 및 수익을 반환해라(통화 형식으로 표시). 최소 수익에서 가장 수익성이 높은 것으로 결과를 분류하고, 결과에 나타나는 계산된 필드의 이름을 변경해야 한다.

Not all of Eastwood’s films were box office successes. Write a subquery that returns a list of movies released between 1980 and 2000 (inclusive) that made a below average profit. Return the movie title, release year, and profit (displayed in currency format). Sort results from least profitable to most profitable. Make sure to rename any calculated fields that appear in the results.

여기서 저는 subquery를 아래와 같이 만들었는데, where까지는 run이 되는데 저 profit계산하는 부분을 넣으면 에러가 뜨네요..SELECT MOVIE.Title
FROM MOVIE
WHERE MOVIE.ReleaseYear BETWEEN 1980 AND 2000
HAVING (MOVIE.BoxOffice-MOVIE.Budget) < AVG(MOVIE.BoxOffice-MOVIE.Budge);

subquery가 에러가 나서 서브쿼리형식말고 서브쿼리없이 전체를 만들어봤는데, 이렇게 하면 "not a GROUP BY expression" 에러가 뜨네요.

SELECT MOVIE.Title, MOVIE.ReleaseYear, (MOVIE.BoxOffice-MOVIE.Budget) AS Profit
FROM MOVIE
WHERE MOVIE.ReleaseYear BETWEEN 1980 AND 2000
GROUP BY MOVIE.Title, MOVIE.ReleaseYear
HAVING (MOVIE.BoxOffice-MOVIE.Budget) < AVG(MOVIE.BoxOffice-MOVIE.Budget)
ORDER BY Profit ASC;

subquery가 어떤 식으로 구성되서 어떻게 전체 쿼리에 녹아드는 지 궁금하네요... 전체 구성이랑 movie 테이블에 관련된 사진첨부합니다.

 

by 마농 [2018.11.06 13:27:50]

SQL 을 작성하는 건 쉬운데
문제를 읽고 해석하는게 더 어렵네요.
문제에 요구사항이 명확하게 제시되어 있질 않네요.
1. 무엇을 출력할 것인가?
  - 이스트우드의 영화를 출력하는 거겠죠? (아까 문제의 연장선?)
  - 모든 영화를 출력하는 건 아니겠죠?
2. 비교 대상이 어떻게 되는가? 평균의 의미가?
  - 전체 영화 평균? vs - 이스트우드 영화의 평균?
  - 전체 영화 평균? vs - 1980년에서 2000년 사이 영화 평균?
3. 수익은 어떻게 구하는가?
  - Budget 은 비용인듯 하고
  - BoxOffice 는 관객수 아닌가요? 이게 매출인가요?
왜? 문제를 내는 사람이 이런 정보들을 부정확하게 내는지 모르겠네요.


by 머루원해 [2018.11.06 13:52:18]

 

넵. 아까 그 데이터에 기반해서 나온 문제입니다.
1. 무엇을 출력할 것인가?  -> subquery와 outer query를 사용하여, 결국엔 query를 만드는 거 같네요.
  - 이스트우드의 영화를 출력하는 거겠죠? (아까 문제의 연장선?) -> 아까랑 같은 데이터에 기반한 문제는 맞는 데 물어보는 것이 달라 서로 연관성은 없는거 같습니다.
  - 모든 영화를 출력하는 건 아니겠죠? -> 정리하면, 먼저 서브쿼리를 만드는 데, 그 서브쿼리에 포함될 내용이 1980년부터 2000년 사이에 출시되고, 그 각각 영화의 수익이 전체 영화의 평균 수익보다 아래에 있는 모든 영화를 나열하는 쿼리를 만드는 것입니다.  수익은 어떤 것을 이용하라고 정확히 명시가 안되있어서 저는 boxoffice(판매량)에서 budget(영화만들때 든 비용)을 뺸 것을 수익으로 정의했어요. 서브쿼리를 만든 다음, 이제 그 쿼리를 넣을 outer query를 만들어야 되는데, outer query에는 영화 제목 (title), 영화 발매년도 (releaseyear), 수익(통화형식으로 표시된 것, 아마 이건 그 subquery에서 만든거라고 보시면 될 것 같습니다)을 나열하는 쿼리를 만드는 것 같습니다.

정리하면,  전체 query를 만들었을 때, 거기에 영화 제목, 영화 발매년도(1980~2000년대 사이에 발매된 것), 수익(평균수익보다 낮은 영화들만)이 나열되면 될 것 같습니다.


2. 비교 대상이 어떻게 되는가? 평균의 의미가? -> 각 영화의 수익을 먼저 구하고, 전체 영화들의 평균을 구한다음에 그거 두개를 비교하는 거 같습니다. 예를 들어서,  첫 번째 영화의 수익은 14,500,000-200,000 (boxoffice - budget) = 14,300,000이고, 두 번째 영화의 수익은 15,000,000-600,000 = 14,400,000이게 되는 거고, 전체 영화의 수익은 첫 번째 영화부터 맨 끝영화까지 수익을 다더한다음 나눈 게 될텐데 oracle에선 avg있으니 이걸 쓰면 될 꺼 같아요. 그리고 이제 1980~2000년 사이에 발매되고, 저 평균수익보다 낮은 수익을 가지는 영화제목을 나열하면되는 거죠.
  
왜? 문제를 내는 사람이 이런 정보들을 부정확하게 내는지 모르겠네요. -> 아마도 학생들 문제라 그런거 같네요 ㅎㅎ


by 마농 [2018.11.06 13:51:56]
SELECT c.Title
     , c.ReleaseYear
     , TO_CHAR(c.BoxOffice - c.Budget, '$999,999,999') AS Profit_1
     , TO_CHAR(c.BoxOffice - c.Budget, 'C999,999,999') AS Profit_2
  FROM movie   c                                -- 3. 영화
 WHERE 1=1
   AND c.MovieID IN (SELECT b.MovieID
                       FROM person         a    -- 1. Eastwood 가
                      INNER JOIN principal b    -- 2. 출연한
                         ON a.PersonID    = b.PersonID
                      WHERE a.PersonFirst = 'Clint'
                        AND a.PersonLast  = 'Eastwood'
                     )
   AND c.ReleaseYear BETWEEN 1980 AND 2000
   AND c.BoxOffice - c.Budget
    <= (SELECT AVG(c.BoxOffice - c.Budget)
          FROM movie   c                                -- 3. 영화
         WHERE 1=1
-- 평균의 대상에 따라 주석 해제 --
--           AND c.MovieID IN (SELECT b.MovieID
--                               FROM person         a    -- 1. Eastwood 가
--                              INNER JOIN principal b    -- 2. 출연한
--                                 ON a.PersonID    = b.PersonID
--                              WHERE a.PersonFirst = 'Clint'
--                                AND a.PersonLast  = 'Eastwood'
--                             )
--           AND c.ReleaseYear BETWEEN 1980 AND 2000
        )
 ORDER BY c.BoxOffice - c.Budget
;

 


by 머루원해 [2018.11.06 14:34:54]

친절한 설명 감사드립니다! 궁금한 부분이 있어서 질문드립니다.

1. SELECT C.Title, C.ReleaseYear, TO_CHAR(C.BoxOffice-C.Budget, '$999,999,999') AS Profit_1, TO_CHAR(C.BoxOffice-C.Budget, 'c999,999,999') AS Profit_2

여기서 profit_1이랑 profit_2랑 차이가 뭔가요?  두번째에서 'c999,999,999'여기서 c가 아니라 $로 넣어야 되는거죠?

2. WHERE에서 1=1이 무엇을 뜻하는 건가요??


by 마농 [2018.11.06 14:40:29]

1. 통화형식으로 표현하라는 모호한 요구사항 때문에 두가지 형태로 답변 드렸습니다.
 - C 는 USD KRW 형태로 출력되구요.
 - $ 는 $ 로 표현됩니다.
2. WHERE 1=1 은
 - 다음 조건절 AND 로 시작하는 구문들에 대해서
 - 주석처리 했다가 풀었다가 하기 편하라고 달이준 것입니다.
 - 1=1 은 항상 참인 조건이죠.
 - 이 또한 모호한 요구사항에 대응하기 위해 그렇게 한 것입니다.


by 머루원해 [2018.11.06 15:34:26]

여러 가지 연습을 통해 이해되었네요 ㅎㅎ

감사합니다 좋은 하루 보내세요!


by 마농 [2018.11.06 16:04:35]

서브쿼리를 이용하는 방식은 쿼리 연습하기에는 좋습니다.
하지만 요즘은 저렇게 안합니다. 분석함수 쓰지요.
 

SELECT Title
     , ReleaseYear
     , Profit
  FROM (SELECT c.Title
             , c.ReleaseYear
             , c.BoxOffice - c.Budget AS Profit
             , AVG(c.BoxOffice - c.Budget) OVER() AS Profit_avg
          FROM movie c
         WHERE 1=1
           AND c.MovieID IN (SELECT b.MovieID
                               FROM person         a
                              INNER JOIN principal b
                                 ON a.PersonID    = b.PersonID
                              WHERE a.PersonFirst = 'Clint'
                                AND a.PersonLast  = 'Eastwood'
                             )
           AND c.ReleaseYear BETWEEN 1980 AND 2000
        )
 WHERE Profit <= Profit_avg
 ORDER BY Profit
;

 

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