このページは、世界最大級のオンライン学習プラットフォームUdemy(ユーデミー)とProglus(プログラス)にて公開している、「はじめてのSQL・データ分析入門」、及び、Proglus(プログラス)にて公開中の「はじめてのSQL ・データ分析入門」 受講生の方向けサポートサイトです。
よくあるご質問、及び、コースで実行するSQL一覧をテキストで掲載しています(一部除く)。
エラーが発生した時に見比べたり、動作するSQLをコピー&ペースとして実行したいときなど、個人の学習用にご利用ください。
MySQL 5.7(.21)、MySQL8.0にて動作確認をしております。その他の環境では動作が異なる場合があります。
目次
- 1 よくあるご質問
- 2 サンプルコード(SQL)
- 3 列を指定してデータを取得する select
- 4 列の値に対して演算を行う
- 4.1 条件を指定してデータを取得する where
- 4.2 比較演算子の種類
- 4.3 パターンマッチングによる絞込 like
- 4.4 取得件数を制限する limit
- 4.5 演習回答:取得件数を制限する limit句
- 4.6 合計値を求める sum集約関数
- 4.7 平均値を求める avg集約関数
- 4.8 最小値を求める min集約関数
- 4.9 最大値を求める max集約関数
- 4.10 対象行の行数を数える count集約関数
- 4.11 応用:月間ユニークユーザー数を求める
- 4.12 データをグループ化 group by
- 4.13 集計をさらに絞り込む having
- 4.14 演習:データの集約
- 4.15 並び替え order by
- 4.16 複数の並び替え条件を指定する
- 4.17 演習回答:データの並び替え
- 4.18 いろいろな算術演算子
- 4.19 nullを含む演算
- 4.20 絶対値の取得 abs
- 4.21 四捨五入 round
- 4.22 文字列の演算
- 4.23 演習回答: 文字列の演算 メルマガ送信用のリスト作成
- 4.24 日付と時刻の演算
- 4.25 内部結合でテーブルを結合する inner join
- 4.26 内部結合 + 絞り込み
- 4.27 演習回答:内部結合
- 4.28 外部結合 left outer join
- 4.29 応用:すべての商品について、販売個数一覧を出力
- 4.30 3つ以上のテーブルを使った結合
- 4.31 多対多の関係を含む結合
- 4.32 テーブルの足し算 union, union all
- 4.33 ビューの作成
- 4.34 ビューの削除
- 5 サブクエリ(where句)
- 6 応用:全商品の平均単価より、高い商品を取得
- 7 応用問題
- 8 データの更新
- 9 注意事項
よくあるご質問
Q. MySQL Workbenchで使えるショートカットを教えてください。
A. 下記の記事を参照してください。
– MySQL Workbenchの便利なショートカット
Q. MySQL 5.7/8.0 for macOSのアンインストール方法を教えてください
A. サポート記事「macOSにHomebrewでインストールしたMySQL5.7, MySQL8.0をアンインストールする方法」を参照してください。
Q. MySQL 5.7 for Windowsのアンインストール方法を教えてください
A. サポート記事「MySQL 5.7 for Windowsのアンインストール方法」を参照してください。
サンプルコード(SQL)
SQL文の基礎
/* データベースの選択 */ use mydb; /* ユーザー一覧の取得 */ select * from users;
演習回答:データを取り出す
select * from products;
コメント
-- select * from users; /* select * from users; select * from products */
よくあるSQLのエラー
select name, price from products; -- DB選択していない use mydb; select * from users; -- スペルミス select * form users; -- 全角文字 select * from users;
列を指定してデータを取得する select
select id, last_name from users;
補足: SQLの書き方
select id, last_name from users; select id, last_name from users; SELECT ID, LAST_NAME FROM USERS; SELECT id, last_name FROM users; SELect ID, LAst_NAme FroM USers; select id, last_name from users LIMIT 0, 1000;
演習回答:列を指定してデータを取得する
select name, price from products;
select name, price from products;
select name as 名前, price as 価格 from products;
select name 名前, price 価格 from products;
列に別名をつける
select name, price from products; select name as 名前, price as 価格 from products; select name 名前, price 価格 from products;
列の値に対して演算を行う
select name as 名前, price as 価格, price * 1.08 as 税込価格 from products;
条件を指定してデータを取得する where
select name, price from products where price >= 9800;
比較演算子の種類
-- 1) products テーブルから全件取得 select * from products; -- 2) idが1の行を取得 select * from products where id = 1; -- 3) 名前が「商品0003」の行を取得 select * from products where name = '商品0003'; -- 4) priceが1000より大きい行を取得 select * from products where price > 1000; -- 5) price が1000より小さい行を取得 select * from products where price < 1000; -- 6) priceが100でない行を取得 select * from products where price <> 100; -- 7) 次のようにもかけます。 select * from products where price != 100; -- 8) idが1か2か3の行を取得 select * from products where id in(1, 2, 3); -- 9)idが1か2か3ではない行を取得 select * from products where id not in(1, 2, 3); -- 10)priceがnullではない行を取得 select * from products where price is not null; -- 11)priceがnullの行を取得 select * from products where price is null; -- 12)priceが1000から1900の行を取得 select * from products where price between 1000 and 1900; -- 13)これは次のようandを使っても書ける。andは、論理積。条件AもBも成り立つ時にtrue(真)。 select * from products where price >= 1000 and price <= 1900; -- 14)or (論理和)も使える。条件Aか条件Bが一つ以上成り立つ場合にtrue -- 価格が1000円又は2000円の行を取得 select * from products where price = 1000 or price = 2000;
パターンマッチングによる絞込 like
select * from users where last_name like '中%'; select * from users where last_name like '%中%'; select * from users where first_name like '%子'; select * from users where first_name like '__子';
取得件数を制限する limit
select * from products limit 10; select * from products limit 0, 10; select * from products limit 10, 10;
演習回答:取得件数を制限する limit句
select id, last_name, gender from users where gender = 1 limit 10;
合計値を求める sum集約関数
-- select * from orders; select sum(amount) from orders where order_time >= '2017-01-01 00:00:00' and order_time < '2017-02-01 00:00:00';
平均値を求める avg集約関数
-- select * from products; select avg(price) from products;
最小値を求める min集約関数
select min(price) from products;
最大値を求める max集約関数
select max(price) from products;
対象行の行数を数える count集約関数
-- select * from users; -- select count(*) from users; select count(*) from users where gender = 2;
応用:月間ユニークユーザー数を求める
-- select * from access_logs; select count(distinct user_id) from access_logs where request_month = '2017-01-01';
データをグループ化 group by
select prefecture_id, count(*) from users group by prefecture_id;
### 応用 : 期間ごとに集計する select request_month, count(distinct user_id) from access_logs where request_month >= '2017-01-01' and request_month < '2018-01-01' group by request_month;
集計をさらに絞り込む having
select request_month, count(distinct user_id) from access_logs where request_month >= '2017-01-01' and request_month < '2018-01-01' group by request_month having count(distinct user_id) >= 630;
演習:データの集約
-- select * from access_logs; select request_month, count(*) from access_logs where request_month >= '2017-01-01' and request_month < '2017-07-01' group by request_month having count(*) >= 1000;
並び替え order by
-- select * from products order by price desc; -- select * from products order by price asc; select * from products order by price;
複数の並び替え条件を指定する
select * from products order by price desc, id asc; select * from products order by price desc, id;
演習回答:データの並び替え
-- 演習 -- ユーザー一覧を、出力。 -- 生年月日が古いに並べる。 -- 生年月日が一緒の場合は、都道府県ID順(昇順)に並べる。 -- select * from users order by birthday asc, prefecture_id asc; select * from users order by birthday, prefecture_id;
いろいろな算術演算子
/* 足し算 */ select 10 + 3; /* 引き算 */ select 10 - 3; /* 掛け算 */ select 10 * 3; /* 割り算 */ select 10 / 3; /* 余り */ select 10 % 3;
nullを含む演算
/* 足し算 */ select 10 + null; /* 引き算 */ select 10 - null; /* 掛け算 */ select 10 * null; /* 割り算 */ select 10 / null; /* 余り */ select 10 % null;
絶対値の取得 abs
/* 10の絶対値 */ select abs(10); /* -10の絶対値 */ select abs(-10); /* 0の絶対値 */ select abs(0);
四捨五入 round
/* 商品価格一覧を作成する時に、税込み価格を出力してほしい。 ただし、小数第1位で四捨五入して出力 */ select id, name, price * 1.08 from products; select id, name, round(price * 1.08, 0) from products; select round(10.555, 0); select round(10.555, 1); select round(10.555, 2);
文字列の演算
/*ユーザー一覧を、 山田 太郎さん というように 名字+スペース+ 名前 + さん の、フォーマットで出力してほしい*/ select concat(last_name, ' ', first_name, 'さん') from users;
演習回答: 文字列の演算 メルマガ送信用のリスト作成
/* 演習 : メルマガ送信用のリスト作成 出力項目は、 宛名「名字 + さん」 メールアドレス 例)中村さん, nakamura@example.com 女性だけに送信したい */ select concat(last_name, 'さん'), email from users where gender = 2;
日付と時刻の演算
/* 現在の日付 ・・・ current_date */ select current_date(); /* 現在の時刻 ・・・ current_timestamp */ select current_timestamp(); /* n日後の日付 ・・・ interval */ select current_date() + interval 3 day; /* n日前の日付 ・・・ interval */ select current_date() - interval 3 day; /* x時間後の時刻 ・・・ interval 'x hour' */ select current_time() + interval 6 hour; /* x時間前の時刻 ・・・ - interval 'x hour' */ select current_time() - interval 6 hour; ### 日付と時刻の演算 /* extract ・・・ 日付や時刻の特定の部分(年や月)までを取り出す。 */ /* ordersテーブルから注文日時(order_timeカラム)が、2017年01月のレコードを取得する。*/ select * from orders where extract(year_month from order_time) = 201701; /* ordersテーブルから注文日時(order_timeカラム)が、2017年のレコードを取得する。*/ select * from orders where extract(year from order_time) = 2017; /* ordersテーブルから注文日時(order_timeカラム)が、1 月のレコードを取得する。*/ select * from orders where extract(month from order_time) = 1;
内部結合でテーブルを結合する inner join
/* 顧客一覧を取得して欲しい。 都道府県IDで出力されてもよくわからないので、都道府県名も表示してほしい。 必要な列は、ユーザーID, 名字, 名前, 都道府県名。*/ /* select users.id, users.last_name, users.first_name, prefectures.name from users inner join prefectures on users.prefecture_id = prefectures.id;*/ select u.id, u.last_name, u.first_name, p.name from users u inner join -- join prefectures p on u.prefecture_id = p.id;
内部結合 + 絞り込み
/* 顧客一覧を取得して欲しい。 都道府県IDで出力されてもよくわからないので、都道府県名も表示してほしい。 必要列は、ユーザーID, 名字, 名前, 都道府県名。 【追加条件】 女性だけのデータが欲しい */ select u.id, u.last_name, u.first_name, p.name from users u inner join prefectures p on u.prefecture_id = p.id where u.gender = 2;
演習回答:内部結合
/* 2017年1月の、東京都に住むユーザーの、注文情報一覧を出して。 取得する列(カラム)は、 注文id (orders.id) 注文日時(orders.order_time) 注文金額合計(orders.amount) ユーザーid (user.id) 名字(users.last_name) 名前(users.first_name) */ select o.id order_id, o.order_time order_time, o.amount amount, u.id user_id, u.last_name last_name, u.first_name first_name from orders o inner join users u on o.user_id = u.id where u.prefecture_id = 13 and o.order_time >= '2017-01-01 00:00:00' and o.order_time < '2017-02-01 00:00:00' order by order_id;
外部結合 left outer join
/* usersテーブルとordersテーブルを結合 */ select u.last_name last_name, u.id user_id, o.user_id order_user_id, o.id order_id from users u -- inner join -- left outer join left join orders o on u.id = o.user_id order by u.id;
応用:すべての商品について、販売個数一覧を出力
/* すべての商品について、販売個数一覧を出して */ select p.id, p.name, sum(od.product_qty) num from products p left outer join -- inner join order_details od on p.id = od.product_id group by p.id ;
3つ以上のテーブルを使った結合
/* 注文一覧を出して欲しい。 注文詳細情報と商品情報も一覧の中に入れて欲しい。*/ select o.id order_id, o.user_id user_id, u.last_name last_name, u.first_name first_name, o.amount amount, o.order_time order_time, p.name product_name, od.product_qty qty, p.price product_price from orders o inner join order_details od on o.id = od.order_id inner join products p on od.product_id = p.id inner join users u on o.user_id = u.id;
多対多の関係を含む結合
select p.id product_id, p.name product_name, c.name category_name from products p inner join products_categories pc on p.id = pc.product_id inner join categories c on c.id = pc.category_id where p.id = 3;
テーブルの足し算 union, union all
/* ユーザーと、アドミンユーザーを足し合わせた一覧が欲しい 出力して欲しい列は、 email 姓 名 性別(性別を表す数字でOK) */ /* select email, last_name, first_name, gender from users union all select email, last_name, first_name, gender from admin_users;*/ select email, last_name, first_name, gender from users where gender = 1 union all select email, last_name, first_name, gender from admin_users where gender = 2 order by gender;
ビューの作成
/* 都道府県別のユーザー数を教えて。*/ /*create view prefecture_user_counts(name, count) as select p.name name, count(*) count from users u inner join prefectures p on u.prefecture_id = p.id group by u.prefecture_id;*/ select name, count from prefecture_user_counts;
ビューの削除
drop view prefecture_user_counts; select name, count from prefecture_user_counts;
サブクエリ(where句)
select id, last_name, email from users where id not in( select user_id from orders where order_time >= '2017-12-01 00:00:00' and order_time < '2018-01-01 00:00:00');
演習回答:サブクエリ
select id, last_name, email from users where id in( select user_id from orders where order_time >= '2017-12-01 00:00:00' and order_time < '2018-01-01 00:00:00');
応用:全商品の平均単価より、高い商品を取得
select * from products where price > ( select avg(price) from products ) order by price desc, id;
条件によって値を変更する
/*ユーザーのアクティビティの度合いによって、施策を変えたい、 ユーザーを累計注文回数で、ランク分けして。 A : 5回以上 B : 2回以上 (2 or 3 or 4) C : 1回 ※注文回数0回のユーザーは出力不要。 必要情報: ユーザーID 累計注文回数 ユーザーランク(A or B or C) */ select u.id as user_id, count(*) as num, case when count(*) >= 5 then 'A' when count(*) >= 2 then 'B' else 'C' end as user_rank from users as u inner join orders as o on u.id = o.user_id group by u.id order by user_rank ;
取得値nullを0を置き換える
select p.id, p.name, case when sum(od.product_qty) is null then 0 else sum(od.product_qty) end as num from products p left outer join order_details od on p.id = od.product_id group by p.id;
演習回答:商品を販売個数でランク分け
/*全商品を累計販売個数で、ランク分けして欲しい。 A : 20個以上 B : 10個以上 C : 10個未満 ランクが高い順に、並び替えて。 必要な列は、商品ID、商品名、販売個数、ランク(A or B or C)*/ select p.id, p.name, sum(product_qty), case when sum(product_qty) >= 20 then 'A' when sum(product_qty) >= 10 then 'B' else 'C' end as product_rank from products p left outer join order_details od on p.id = od.product_id group by p.id order by product_rank ;
応用問題
平均客単価
/*全期間での平均客単価を教えて 補足:単価は小数第一位で四捨五入*/ select round(avg(amount), 0) from orders;
月別平均客単価
/*月別の平均客単価を教えて 補足 小数第一位で四捨五入。 必要な列 年月 平均客単価*/ select date_format(order_time, '%Y%m') as order_year_month, round(avg(amount), 0) as average_customer_spend from orders group by date_format(order_time, '%Y%m') order by order_year_month ;
都道府県別平均客単価
/*都道府県別平均客単価を教えてほしい。 必要な列 都道府県ID 都道府県名 平均客単価(小数第1位で四捨五入) 並び順 都道府県ID昇順 全期間での平均客単価を教えて*/ select pref.id as prefecture_id, pref.name as prefecture_name, round(avg(o.amount), 0) as average_customer_spend from orders o inner join users u on o.user_id = u.id inner join prefectures pref on u.prefecture_id = pref.id group by pref.id order by pref.id ;
都道府県別・月別平均客単価
/* 都道府県別・月別平均客単価を教えて 必要な列 都道府県ID 都道府県名 年月 平均客単価(小数第1位で四捨五入) 並び順 都道府県ID昇順, 年月昇順 */ select pref.id as prefecture_id, pref.name as prefecture_name, date_format(o.order_time, '%Y%m') as order_year_month, round(avg(o.amount), 0) as average_customer_spend from orders o inner join users u on o.user_id = u.id inner join prefectures pref on u.prefecture_id = pref.id group by prefecture_id, order_year_month order by prefecture_id, order_year_month ;
データの更新
レコードを1件追加する insert
insert into products (name, price) values ('新商品A', 1000); select * from products;
列リストを省略して1件行を追加する
select * from products; insert products values(1002, '新商品B', 2000); select * from products;
行を複数追加する
/*新商品を3件データベースに追加してほしい。 */ 商品名:新商品C 価格:3,000 商品名:新商品D 価格:4,000 商品名:新商品E 価格:5,000*/ insert into products (name, price) values ('新商品C', 3000), ('新商品D', 4000), ('新商品E', 5000); select * from products;
行の更新 update
/* 全商品を10%引きに設定して。*/ select * from products; set sql_safe_updates = 0; update products set price = price * 0.9; select * from products;
特定の条件に合致する行を更新 update
/* 商品idが3の商品名を、「SQL入門」に変えておいて。*/ select * from products where id = 3; update products set name = 'SQL入門' where id = 3; select * from products where id = 3; update products set name = 'SQL入門1', price = 1000 where id = 3; select * from products where id = 3;
更新条件にサブクエリを使う
/*累計販売数が10個以上の商品については、 価格を5%UPして。*/ select product_id, sum(product_qty) from order_details group by product_id having sum(product_qty) >= 10; select * from products; update products set price = price * 1.05 where id in ( select product_id from order_details group by product_id having sum(product_qty) >= 10 ); select * from products;
行の削除
/*今、商品に割り振られている商品カテゴリを使うのをやめるので、 商品とカテゴリのひも付きを削除してほしい*/ select * from products_categories; delete from products_categories; select * from products_categories;
条件を指定して、行の削除
/* 商品ID 1001は、 間違いで登録してしまったものだから、削除してほしい。*/ select * from products where id = 1001; delete from products where id = 1001; select * from products where id = 1001;
削除条件にサブクエリを使う
/* 一個も売れていない商品は、売るのをやめるので削除して。*/ select product_id from order_details group by product_id; delete from products where id not in( select product_id from order_details group by product_id ); select * from products;
データベースの作成
show databases; create database book_store; show databases;
テーブルの追加
use book_store; show tables; create table books(id int not null auto_increment primary key, title varchar(255) not null); show tables; show columns from books;
テーブル構造の変更
show columns from books; alter table books add price int after id; show columns from books; alter table books change price unit_price int; show columns from books; alter table books drop unit_price; show columns from books;
テーブルの削除
show tables; drop table books; show tables;
データベースの削除
show databases; drop database book_store; show databases;
注意事項
受講生の皆さんの個人的な学習にのみご利用いただけます。
営利・非営利問わず二次利用する行為を禁止します。