아무도 안 들어온 달도 0으로
문제
달마다 등록한 회원 수를 그림으로 그리려 한다. 그런데 앞 문제의 방식으로는 아무도 등록하지 않은 달이 줄에서 빠져 버린다. 그림을 그리는 쪽에서는 모든 달이 줄로 있어야 하고, 아무도 없는 달은 0 으로 와야 한다고 한다.
1월부터 8월까지 여덟 달에 대하여, 달과 그 달에 등록한 회원 수를 달 오름차순으로 조회하여라. 등록한 회원이 없는 달도 0 으로 나와야 한다.
줄은 늘 여덟 줄이다. 자료에 어느 달이 있든 없든 여덟 줄이다. 자료에 없는 달을 만들어 내야 하므로, 자료를 보는 것만으로는 안 된다. 1 에서 8 까지의 달 목록을 먼저 만들고 거기에 자료를 붙이는 쪽으로 생각해 보아라.
첫째 벌에서의 결과
첫째 벌의 자료에 대하여 나와야 하는 결과입니다. 나머지 열다섯 벌에서는 값과 줄의 수가 다릅니다.
| month | cnt |
|---|---|
| 1 | 0 |
| 2 | 0 |
| 3 | 0 |
| 4 | 0 |
| 5 | 2 |
| 6 | 1 |
| 7 | 2 |
| 8 | 2 |
입력 조건
이 문제의 자료에는 표가 둘 있습니다.
registered_member 는 지금 등록되어 있는 회원입니다.
| 칸 | 형 | 뜻 |
| --- | --- | --- |
| id | INTEGER | 회원 번호. 표 안에서 겹치지 않습니다 |
| name | VARCHAR(20) | 이름. 한 벌 안에서 겹치지 않습니다 |
| age | INT | 나이 |
| gender | VARCHAR(10) | 성별. '남성' 과 '여성' 두 가지이고, 한 벌에 둘 다 있습니다 |
| address | VARCHAR(100) | 사는 지역. 없을 수 있습니다(NULL) |
| grade | INT | 등급. 1 에서 5 사이의 정수이고, 큰 값이 높은 등급입니다 |
| datetime | DATETIME | 등록한 때. '2012-05-03 13:00:00' 꼴의 글이고 겹치지 않습니다 |
retired_member 는 탈퇴한 회원입니다. 칸은 registered_member 와 같고, datetime 이 탈퇴한 때를 뜻합니다. 탈퇴할 때의 등급이 등록할 때와 다를 수 있습니다.
두 표에 같은 번호로 있는 줄은 같은 사람이고 이름도 같습니다. 탈퇴 표에만 있는 번호가 있을 수 있습니다. 등록 표에만 있는 번호도 있을 수 있습니다.
이 문제는 registered_member 의 datetime 을 봅니다. 등록일의 연도는 모든 벌에서 2012년입니다.
자료는 열여섯 벌이 있습니다. 표의 짜임과 칸은 열여섯 벌이 모두 같고, 들어 있는 값과 줄의 수가 벌마다 다릅니다. 낸 질의는 열여섯 벌 위에서 차례로 돌고, 열여섯 벌의 결과가 모두 맞아야 통과합니다.
첫째 벌의 자료는 문제 화면의 [자료] 칸에 있습니다. 나머지 열다섯 벌은 화면에 안 그려지지만, 질의가 당신 브라우저에서 도는 구조라 열여섯 벌이 모두 당신 기기로 내려갑니다. 보시려면 보실 수 있습니다. 숨겨 둔 척하지 않겠습니다.
그래서 한 벌이 아니라 열여섯 벌로 두었습니다. 한 벌이면 결과만 외워 적어도 통과합니다. 열여섯 벌이면 외워 적은 답이 그 벌에서만 맞습니다. 열여섯 벌의 답을 모두 손으로 적어 내는 길이 남아 있기는 한데, 낸 질의는 푼 사람 칸에 그대로 걸립니다. 막는 쪽보다 드러나는 쪽을 골랐습니다. 기대하는 결과의 지문은 서버만 가지고 있어서, 내보기 전에는 맞는지 확인할 수 없습니다.
출력 조건
1월부터 8월까지 여덟 달의 달과 회원 수를 달 오름차순으로 출력합니다.
칸은
month,cnt두 개이고 이 차례입니다. 두 칸 모두AS로 이름을 맞춥니다.month는 수입니다. 1월이1이고01이 아닙니다. 앞 문제와 반대이므로 주의하여라. 달 목록을 1 에서 8 까지의 수로 만들었다면 그 수를 그대로 내보내면 됩니다.줄은 늘 여덟 줄이고, 회원이 없는 달의
cnt는 0 입니다.채점은 칸 이름과 값과 줄 순서를 모두 견줍니다. 칸 이름이 다르면 값이 맞아도 틀린 것으로 봅니다. 그래서 필요한 칸 이름을 위에 적어 두었고, 그 이름이 나오도록
AS를 쓰면 됩니다.
요구사항
- 줄은 늘 여덟 줄입니다. 1월부터 8월까지입니다
- 칸은 month, cnt 두 개입니다
- month 는 1 부터 8 까지의 수입니다. 두 자리 글이 아닙니다
- 회원이 없는 달의 cnt 는 0 입니다
- 달 오름차순으로 세웁니다
- 이 문제는 프롬프트가 아니라 질의(SQL)를 냅니다. 그 질의는 이 기기의 브라우저에 올라온 SQLite 에서 돌고, 서버로는 나온 결과표의 지문만 갑니다. 맞았는지는 서버가 정합니다.
- 견주는 것은 글이 아니라 결과표입니다. 칸 이름과 값과 줄 순서를 모두 봅니다. 칸 이름이 다르면 값이 맞아도 틀린 것으로 봅니다.
- 자료는 16벌입니다. 첫째 벌은 화면에 그려지고, 나머지도 질의가 당신 기기에서 돌기 때문에 모두 내려갑니다.
- 자료 16벌의 결과가 모두 맞아야 해결입니다.
참고 사항
풀이에 도움이 되는 배경입니다. 지켜야 하는 규격은 위의 입출력 조건과 요구사항에 있습니다.
자료에 없는 달을 만들어 내려면 수 목록을 스스로 만드는 길이 필요합니다. sqlite3 에서는 WITH RECURSIVE 로 만듭니다.
WITH RECURSIVE temp AS ( SELECT 1 AS month UNION ALL SELECT month + 1 FROM temp WHERE month < 8 )
끝나는 조건(month < 8)을 빠뜨리면 멈추지 않습니다. 멈추지 않는 질의는 20초 뒤에 끊기고 그 까닭이 화면에 나옵니다.
만든 목록에 자료를 붙일 때는 LEFT JOIN 을 씁니다. 달 쪽을 왼쪽에 두어야 회원이 없는 달이 남습니다. 그리고 셀 때 COUNT(*) 가 아니라 COUNT(회원 쪽 칸) 을 세어야 0 이 나옵니다. COUNT(*) 는 붙지 않은 줄도 1 로 세기 때문입니다.
MySQL 에서는 사용자 변수(SET @month = 0)로 같은 일을 하는 길이 있습니다.
SQLite 로 풀기
답이 가져야 하는 칸 month, cnt
자료
첫째 벌입니다. 나머지 0벌은 짜임이 같고 값이 다릅니다.
자료를 받고 있습니다
질의
돌려보기는 첫째 벌에서만 돌리고 서버에 보내지 않습니다. 맞았는지는 제출하셔야 알 수 있습니다.
이 문제를 푼 사람
아직 없습니다. 첫 번째가 되실 수 있습니다.