# 非エンジニアのためのSQL 演習問題 ## これは 『非エンジニアのためのSQL』 https://hackmd.io/@Ikazuchi/HkVpqeowr の演習問題集です。 ## もくじ [TOC] ## hackerrankについて この文書では、演習問題として https://www.hackerrank.com/ の問題を用いる。 そのため、事前にアカウント登録を行っておくとスムーズである。 Sign Upにgoogleアカウントを指定すると即座にアカウント登録できるが、言語を選ばされいきなり普通の問題に入ってしまうのでそのあたりでページを閉じ、下記演習問題のアドレスにアクセスするとよい。 本資料は基本的にMySQLに準拠するため、処理系はMySQLを選択すること。 ## 演習問題 ### select句とfrom句 #### Select All https://www.hackerrank.com/challenges/select-all-sql/problem **CITY**テーブルの全ての行、全てのカラムを出力するクエリを書け。 ### where句 #### Select By ID https://www.hackerrank.com/challenges/select-by-id/problem `id`が1661のレコードの全てのカラムを出力せよ。 #### Japanese Cities Attributes https://www.hackerrank.com/challenges/japanese-cities-attributes/problem 日本の都市の全てのカラムを出力せよ。ただし、日本の国コードは`JPN`である。 #### Weather Observation Station 3 https://www.hackerrank.com/challenges/weather-observation-station-3/problem IDが偶数の都市の名前の一覧を出力せよ。ただし、出力は重複しないようにすること。 #### Revising the Select Query II https://www.hackerrank.com/challenges/revising-the-select-query-2/problem 人口が12万を超えるようなアメリカの都市名の一覧を出力せよ。ただし、アメリカの国コードは`USA`である。 ### 集計関数 #### Revising Aggregations - The Sum Function https://www.hackerrank.com/challenges/revising-aggregations-sum/problem 地区がカリフォルニアの都市の人口の合計を出力せよ。 #### Revising Aggregations - The Count Function https://www.hackerrank.com/challenges/revising-aggregations-the-count-function/problem 人口が10万を超える都市の数を求めよ。 #### Revising Aggregations - Averages https://www.hackerrank.com/challenges/revising-aggregations-the-average-function/problem 地区がカリフォルニアの都市の人口の平均を出力せよ。 #### Population Density Difference https://www.hackerrank.com/challenges/population-density-difference/problem 人口が最大の都市の人口と、最小の都市の人口の差を求めよ。 #### Weather Observation Station 4 https://www.hackerrank.com/challenges/weather-observation-station-4/problem **STATION**テーブルに含まれる都市の数をNとし、同じく互いに異なる都市の数をN'としたときに、N-N'を求めよ。 ### group by句 + having句 HackerRankに`group by`を用いた練習問題がないので、シンプルな例を出す。 #### #1 以下のテーブルが与えられたとき、ユーザごとのスコアの合計を求めるクエリを書け。 **scores** |カラム名|データの例| |-|-| |user_id|12345| |score|12345| |date|2018-01-01| #### #2 **scores**テーブルが与えられたとき、日付ごとのスコアの合計が30より大きいような日付とそのスアの合計を求めるクエリを書け。 #### #3 **scores**テーブルが与えられたとき、日付ごとのスコアの合計が30より大きいような日付を求めるクエリを書け。 ### テーブルの結合 #### African Cities https://www.hackerrank.com/challenges/african-cities/problem **CITY**テーブルと**COUNTRY**テーブルが与えられる。 アフリカ大陸の国の都市の一覧を出力せよ。 #### Asian Population https://www.hackerrank.com/challenges/asian-population/problem アジア大陸のすべての都市の人口の和を出力せよ。 #### Average Population of Each Continent https://www.hackerrank.com/challenges/average-population-of-each-continent/problem 大陸名と、大陸ごとの都市の人口の平均(小数点以下切り捨て)を求めよ。 ただし、`x`の小数点切り捨ては`truncate(x, 0)`と書く。 #### Top Competitors https://www.hackerrank.com/challenges/full-score/problem Juliaはコーディングテストの開催を終え、その順位表を作ろうとしており、あなたの助けが必要である。 複数の問題で満点を取ったハッカーの`hacker_id`と名前を求めるクエリを書け。 ただし、出力は満点を取った問題が多い参加者から順番に並べ、同じ場合は`hacker_id`が若い順に並べよ。 ##### 入力 **Hackers** `hacker_id`はハッカーのid、`name`はハッカーの名前である。 **Difficulty** `difficult_level`は問題の難易度で、`score`はその難易度の問題の満点である。 **Challenges** `challenge_id`は問題のid、`hacker_id`は問題作成者のhacker_id、`difficulty_level`は難易度である。 **Submissions** `submission_id`は提出のid、`hacker_id`は提出者のhacker_id、`challenge_id`は提出した問題のid、`score`はその提出で得られた得点である。 #### New Companies https://www.hackerrank.com/challenges/the-company/problem アンバーの経営する大企業は、ちょうど何社かの新しい会社を買収したところである。 各企業は、次のような階層構造になっている。 ``` 創業者→リードマネージャ→シニアマネージャ→マネージャ→労働者 ``` 以下の入力を用いて、各会社のcompany_codeと創業者の名前、リードマネージャの数、シニアマネージャの数、マネージャの数、労働者の数を求めるクエリを書け。ただし、出力はcompany_codeの昇順とする。 ##### 注意事項 - 各テーブルには、重複したレコードが含まれる可能性がある。 - company_codeは文字列であるから、`C_1`、`C_2`、`C_10`が与えられた場合その昇順とは、`C_1`、`C_10`、`C_2`の順である。 ##### 入力 **Company** `company_code`は会社ごとに振られているコード、`founder`は創業者の名前である。 **Lead_Manager** `lead_manager_code`はリードマネージャのコード、`company_code`はそのリードマネージャが勤めている会社のコードである。 **Senior_Manager** `senior_manager_code`はシニアマネージャのコード、`lead_manager_code`はそのシニアマネージャの上司のリードマネージャのコード、`company_code`はそのシニアマネージャが勤めている会社のコードである。 **Manager** `manager_code`はマネージャのコード、`senior_manager_code`はそのマネージャの上司のシニアマネージャのコード、`lead_manager_code`はそのマネージャの上司のリードマネージャのコード、`company_code`はそのマネージャが勤めている会社のコードである。 **Employee** `employee_code`はその労働者のコード、`manager_code`はその労働者の上司のマネージャのコード、`senior_manager_code`はその労働者の上司のシニアマネージャのコード、`lead_manager_code`はその労働者の上司のリードマネージャのコード、`company_code`はその労働者が勤めている会社のコードである。 ### サブクエリ #### Contest Leaderboard https://www.hackerrank.com/challenges/contest-leaderboard/problem 前回のコンテストで素晴らしい仕事をしたあなたは、Juliaに次の仕事をしてほしいと言われた。 ハッカーの合計スコアは、それぞれの問題に対する最高得点の和である。 hacker_id、ハッカーの名前、合計スコアを合計スコアの降順で求めるクエリを書け。 ただし、複数のハッカーが同じ合計スコアを持つ場合、hacker_idの昇順で並べよ。 また、合計スコアが0のハッカーは取り除け。 ##### 入力 **Hackers** `hacker_id`はハッカーのid、`name`はハッカーの名前である。 **Submissions** `submission_id`は提出のid、`hacker_id`は提出者のhacker_id、`challenge_id`は提出した問題のid、`score`はその提出で得られた得点である。 ## 回答例 ### select句とfrom句 #### Select All ```sql= select * from city ``` ### where句 #### Select By ID ```sql= select * from city where id = 1661 ``` #### Japanese Cities Attributes ```sql= select * from city where countrycode = 'JPN' ``` #### Weather Observation Station 3 ```sql= select distinct city from station where id % 2 = 0 ``` #### Revising the Select Query II ```sql= select name from city where population > 120000 and countrycode = 'USA' ``` ### 集計関数 #### Revising Aggregations - The Sum Function ```sql= select sum(population) from city where district = 'California' ``` #### Revising Aggregations - The Count Function ```sql= select count(*) from city where population > 100000 ``` #### Revising Aggregations - Averages ```sql= select avg(population) from city where district = 'California' ``` #### Population Density Difference ```sql= select max(population) - min(population) from city ``` #### Weather Observation Station 4 ```sql= select count(city) - count(distinct city) from station ``` ### group by句 + having句 #### #1 ```sql= select user_id , sum(score) as s from scores group by user_id ``` #### #2 ```sql= select date , sum(score) as s from scores group by date having s > 30 ``` #### #3 ```sql= select date from scores group by date having sum(score) > 30 ``` ### テーブルの結合 #### African Cities ```sql= select city.name from city inner join country on city.countrycode = country.code where country.continent = 'Africa' ``` #### Asian Population ```sql= select sum(ci.population) from city as ci inner join country as co on ci.countrycode = co.code where co.continent = 'Asia' ``` #### Average Population of Each Continent ```sql= select co.continent , truncate(avg(ci.population), 0) from city as ci inner join country as co on ci.countrycode = co.code group by co.continent ``` #### Top Competitors ```sql= select h.hacker_id , h.name from hackers as h inner join submissions as s using(hacker_id) inner join challenges as c using(challenge_id) inner join difficulty as d using(difficulty_level) where d.score = s.score group by h.hacker_id , h.name having count(distinct s.challenge_id) > 1 order by count(distinct s.challenge_id) desc , h.hacker_id ``` #### New Companies ```sql= select c.company_code , c.founder , count(distinct l.lead_manager_code) , count(distinct s.senior_manager_code) , count(distinct m.manager_code) , count(distinct e.employee_code) from company as c left join lead_manager as l on c.company_code = l.company_code left join senior_manager as s on c.company_code = s.company_code left join manager as m on c.company_code = m.company_code left join employee as e on c.company_code = e.company_code group by c.company_code , c.founder order by c.company_code ``` ### サブクエリ #### Contest Leaderboard ```sql= select hacker_id , name , sum(max_score) as sum_score from ( select h.hacker_id , h.name , s.challenge_id , max(score) as max_score from hackers as h inner join submissions as s on h.hacker_id = s.hacker_id group by h.hacker_id , h.name , s.challenge_id ) as a group by hacker_id , name having sum_score != 0 order by sum_score desc , hacker_id ```