Prepare > SQL > Advanced Join > 15 Days of Learning SQL
https://www.hackerrank.com/challenges/15-days-of-learning-sql/problem?isFullScreen=true
15 Days of Learning SQL | HackerRank
find users who submitted a query every day.
www.hackerrank.com
문제
Julia conducted a 15days of learning SQL contest. The start date of the contest was March 01, 2016 and the end date was March 15, 2016.
Write a query to print total number of unique hackers who made at least 1 submission each day (starting on the first day of the contest), and find the hacker_id and name of the hacker who made maximum number of submissions each day. If more than one such hacker has a maximum number of submissions, print the lowest hacker_id. The query should print this information for each day of the contest, sorted by the date.
=> 15일간 SQL콘테스트가 있었다. 16.03.01 시작했다. 콘테스트의 첫 날 부터 매일 1개 이상 제출한 해커의 수, 각각의 날에 최다 제출자의 ID와 NAME을 출력하는 쿼리문을 써라. 최다 제출수가 같으면 ID로 뽑고, 날짜로 정렬해라.
코드
SELECT
submission_date,
(
SELECT COUNT(distinct hacker_id)
FROM SUBMISSIONS AS S2
WHERE S2.submission_date = S1.submission_date
AND DATEDIFF(S1.submission_date , '2016-03-01') = (
SELECT COUNT(distinct S3.submission_date)
FROM Submissions AS S3
WHERE S3.hacker_id = S2.hacker_id
AND S3.submission_date < S1.submission_date)
),
(
SELECT hacker_id
FROM submissions AS S2
WHERE S2.submission_date = S1.submission_date
GROUP BY hacker_id
ORDER BY COUNT(submission_id) DESC , hacker_id limit 1
) AS shit,
(
SELECT name FROM hackers WHERE hacker_id = shit
)
FROM (SELECT DISTINCT(submission_date) from SUBMISSIONS) AS S1
GROUP BY submission_date;
OUTPUT
2016-03-01 112 81314 Denise
2016-03-02 59 39091 Ruby
2016-03-03 51 18105 Roy
2016-03-04 49 533 Patrick
2016-03-05 49 7891 Stephanie
2016-03-06 49 84307 Evelyn
2016-03-07 35 80682 Deborah
2016-03-08 35 10985 Timothy
2016-03-09 35 31221 Susan
2016-03-10 35 43192 Bobby
2016-03-11 35 3178 Melissa
2016-03-12 35 54967 Kenneth
2016-03-13 35 30061 Julia
2016-03-14 35 32353 Rose
2016-03-15 35 27789 Helen
노트
1. 정답의 전체적인 구조부터 파악
SELECT
[고유한 제출일],
[성실한 인원 수]에 대한 쿼리,
[제출일 별 최다 제출자 ID]에 대한 쿼리,
[제출일 별 최다 제출자 NAME]에 대한 쿼리
FROM SUBMISSINOS
- 서브쿼리를 SELECT 에 넣어서 조회할 대상을 다양하게 설정할 수 있음
2. 고유한 제출일
SELECT
submission_date
FROM (SELECT DISTINCT(submission_date) from SUBMISSIONS) AS S1
GROUP BY submission_date;
- 내가 쓴 답이 아니라 왜 이렇게 S1을 저렇게 설정했는지는 모름
- S1은 고유한 제출일을 조회하는 전체 컬럼으로서 기억해두자
OUTPUT
2016-03-01
2016-03-02
2016-03-03
2016-03-04
2016-03-05
2016-03-06
2016-03-07
2016-03-08
2016-03-09
2016-03-10
2016-03-11
2016-03-12
2016-03-13
2016-03-14
2016-03-15
3. [성실한 인원 수]에 대한 쿼리
SELECT COUNT(distinct hacker_id) # 고유한 해커ID
FROM SUBMISSIONS AS S2
WHERE S2.submission_date = S1.submission_date # 앞서 조회한 날짜에 해당하는 결과값을 조회해야함
AND
DATEDIFF(S1.submission_date , '2016-03-01') = ( # 제출일 - 시작일
SELECT COUNT(distinct S3.submission_date) # 이때까지 제출한 날짜의 수
FROM Submissions AS S3
WHERE S3.hacker_id = S2.hacker_id # 조회하려는 해커ID(위의 고유한 해커ID)에 대해 일치시킴
AND S3.submission_date < S1.submission_date) # 6.10일에서 보는 중인데 6.12일 데이터가 끼어들지 못하게끔
- 조회하려는 [해커ID(위의 고유한 해커ID)가 이때까지 제출한 날짜의 수] 와 [제출일 - 시작일] 의 값이 같으면 되는거 아니야??
INPUT
SELECT
submission_date,
(
SELECT COUNT(distinct hacker_id)
FROM SUBMISSIONS AS S2
WHERE S2.submission_date = S1.submission_date
AND DATEDIFF(S1.submission_date , '2016-03-01') = (
SELECT COUNT(distinct S3.submission_date)
FROM Submissions AS S3
WHERE S3.hacker_id = S2.hacker_id
AND S3.submission_date < S1.submission_date)
)
FROM (SELECT DISTINCT(submission_date) from SUBMISSIONS) AS S1
GROUP BY submission_date;
OUTPUT
2016-03-01 112
2016-03-02 59
2016-03-03 51
2016-03-04 49
2016-03-05 49
2016-03-06 49
2016-03-07 35
2016-03-08 35
2016-03-09 35
2016-03-10 35
2016-03-11 35
2016-03-12 35
2016-03-13 35
2016-03-14 35
2016-03-15 35
4. [제출일 별 최다 제출자 ID]에 대한 쿼리
SELECT hacker_id
FROM submissions AS S2
WHERE S2.submission_date = S1.submission_dat # 앞서 조회한 날짜에 해당하는 결과값을 조회해야함
GROUP BY hacker_id
ORDER BY COUNT(submission_id) DESC , hacker_id limit 1
- 이제 이정도는 뚝딱 해석 가능
INPUT
SELECT
submission_date,
(
SELECT COUNT(distinct hacker_id)
FROM SUBMISSIONS AS S2
WHERE S2.submission_date = S1.submission_date
AND DATEDIFF(S1.submission_date , '2016-03-01') = (
SELECT COUNT(distinct S3.submission_date)
FROM Submissions AS S3
WHERE S3.hacker_id = S2.hacker_id
AND S3.submission_date < S1.submission_date)
),
(
SELECT hacker_id
FROM submissions AS S2
WHERE S2.submission_date = S1.submission_date
GROUP BY hacker_id
ORDER BY COUNT(submission_id) DESC , hacker_id limit 1
)
FROM (SELECT DISTINCT(submission_date) from SUBMISSIONS) AS S1
GROUP BY submission_date;
OUTPUT
2016-03-01 112 81314
2016-03-02 59 39091
2016-03-03 51 18105
2016-03-04 49 533
2016-03-05 49 7891
2016-03-06 49 84307
2016-03-07 35 80682
2016-03-08 35 10985
2016-03-09 35 31221
2016-03-10 35 43192
2016-03-11 35 3178
2016-03-12 35 54967
2016-03-13 35 30061
2016-03-14 35 32353
2016-03-15 35 27789
5. [제출일 별 최다 제출자 NAME]에 대한 쿼리
- 앞서 조회한 "제출일 별 최다 제출자ID"를 보고 이름만 가져오면 됨
(
SELECT hacker_id
FROM submissions AS S2
WHERE S2.submission_date = S1.submission_date
GROUP BY hacker_id
ORDER BY COUNT(submission_id) DESC , hacker_id limit 1
) AS shit, # 별칭 붙여주기
- 4번 쿼리에 별칭을 붙여준다
SELECT name FROM hackers WHERE hacker_id = shit
- 이름 가져옴
6. 종합
SELECT
submission_date,
(
SELECT COUNT(distinct hacker_id)
FROM SUBMISSIONS AS S2
WHERE S2.submission_date = S1.submission_date
AND DATEDIFF(S1.submission_date , '2016-03-01') = (
SELECT COUNT(distinct S3.submission_date)
FROM Submissions AS S3
WHERE S3.hacker_id = S2.hacker_id
AND S3.submission_date < S1.submission_date)
),
(
SELECT hacker_id
FROM submissions AS S2
WHERE S2.submission_date = S1.submission_date
GROUP BY hacker_id
ORDER BY COUNT(submission_id) DESC , hacker_id limit 1
)
FROM (SELECT DISTINCT(submission_date) from SUBMISSIONS) AS S1
GROUP BY submission_date;
참조
15 days of learning SQL
www.hackerrank.com/challenges/15-days-of-learning-sql/problem 15 Days of Learning SQL | HackerRank find users who submitted a query every day. www.hackerrank.com 해결 방법 : 서브 쿼리 JOIN 현재까지 매일 submission하고 있는 사람을 구
profailure.tistory.com
여기는 내가 고생했던 흔적들....ㅋ 그냥 남겨보고 싶었어
제출일 = 그냥 가능
매일제출한인원 수 = ...?
일일 최다 제출 해커 = 일자별 해커별 count(submission_id)
SELECT
SB.submission_date,
SB.hacker_id,
COUNT(SB.submission_id) AS k1
FROM SUBMISSIONS AS SB
LEFT JOIN HACKERS AS H ON SB.hacker_id = H.hacker_id
GROUP BY SB.submission_date, SB.hacker_id
ORDER BY SB.submission_date, SB.hacker_id
;
SELECT
SB.submission_date,
SB.hacker_id,
COUNT(SB.submission_id) AS k1
FROM SUBMISSIONS AS SB
LEFT JOIN HACKERS AS H ON SB.hacker_id = H.hacker_id
GROUP BY SB.submission_date, SB.hacker_id
ORDER BY SB.submission_date, SB.hacker_id
;
매일 제출한 인원 파악
인원별 count(submission_date) : 띄엄띄엄 낸건 어쩔건데
case
when 날짜별 제출 인원 리스트에 포함 , 1??
submission_date - start_date = 인원별 count(submission_date) from submission as s1 where s1.submission_date <= s2.submissiond_date
SELECT
S1.hacker_id,
DATEDIFF(S1.submission_date, '2016.03.01')
FROM SUBMISSIONS AS S1
WHERE
DATEDIFF(S1.submission_date, '2016.03.01') = # 제출일-시작일 값이 이때까지의 제출일 수 와 같으면?
(SELECT COUNT(DISTINCT(S2.submission_date)) FROM SUBMISSIONS AS S2
WHERE S2.submission_date <= S1.submission_date AND S1.hacker_id = S2.hacker_id
GROUP BY hacker_id)
SELECT DATEDIFF(S2.submission_date, '2016-03-01')
FROM SUBMISSIONS AS S2
WHERE DATEDIFF(S2.submission_date, '2016-03-01') =
(SELECT COUNT(DISTINCT(S3.submission_id)) FROM SUBMISSIONS AS S3
WHERE S3.submission_date <= S2.submission_date AND S3.hacker_id = S2.hacker_id
GROUP BY S3.hacker_id)
SELECT
S1.submission_date,
SELECT K1 FROM (
SELECT DATEDIFF(S1.submission_date, '2016-03-01') AS K1 FROM SUBMISSIONS AS S2
WHERE DATEDIFF(S1.submission_date, '2016-03-01') <=
(SELECT COUNT(DISTINCT(S3.submission_id)) FROM SUBMISSIONS AS S3
WHERE S1.
)
FROM SUBMISSIONS AS S1
LEFT JOIN HACKERS AS H ON S1.hacker_id = H.hacker_id
GROUP BY S1.submission_date
ORDER BY S1.submission_date
SELECT
S.submission_date AS submission_date,
S.hacker_id AS hacker_id,
H.name AS name,
S.submission_id AS submission_id,
S.score AS Score
FROM SUBMISSIONS AS S
LEFT JOIN HACKERS AS H ON S.hacker_id = H.hacker_id
ORDER BY S.submission_date