前回の記事ではMySQLのデータの抽出に関しておもにみてきました。
今回はデータの集計やテーブルの結合なでについて書いています。
データの集計
※users_teamテーブルがあるものして書いています。
データの集計で使える関数にはおもに以下のようなものがあります。
- count()⇀ レコードの数をカウントする
- sum()⇀ 合計
- min()⇀ 最小値
- max()⇀ 最大値
- avg()⇀ 平均値
select count(*) from users_team; select min(score) from users_team; select max(score) from users_team; select avg(score) from users_team;
distinkt
distinktを使用するとレコードを重複したレコードを分類してくれます。distinctはカラム名を指定します。
count(distinkt)とすると重複したレコードをとりぞいた状態での数を取得できます
select distinct fieldname from users_team; select count(distinct) fieldname from users_team;
group by、having
group byはグループ集計で使用します
select sum(round(score)), team from users_team group by team;
グループ化したあとのデータに条件を指定して抽出するにはwhereではなくhavingを使います。havingはグループ化したカラムや集計した値にしかつかうことができません。
select sum(round(score)), team from users_team group by team having sum(score) > 10;
group byはwhereと一緒に使うこともできます。その場合はwhereで抽出したあとのデータがグループ化されます。
select sum(round(score)), team from users_team where id > 2 group by team having sum(score) > 10;
サブクエリ
サブクエリはややこしいのでコードだけのせときます。
–users_alphaテーブル–
+—-+——–+——-+
| id | name | score |
+—-+——–+——-+
| 1 | suzuki | 10 |
| 2 | tanaka | 20 |
| 3 | saito | 15 |
+—-+——–+——-+
select sum(alpha.score) from( select * from users_alpha ) as alpha;
+——————+
| sum(alpha.score) |
+——————+
| 45 |
+——————+
view
viewをつかうと抽出条件をまとめて他で使うことができます
drop table if exists users_alpha;
create table users_alpha(
id int unsigned primary key auto_increment,
name varchar(16),
score int default 1
);
insert into users_alpha(name, score) values
('hamaguti', 10),
('matuguti', 20),
('kuramoto', 30),
('tanaka', 40),
('suzuki', 50),
('saito', 60);
create view top3 as select * from users_alpha order by score desc limit 3;
select * from top3;
+----+--------+-------+
| id | name | score |
+----+--------+-------+
| 6 | saito | 60 |
| 5 | suzuki | 50 |
| 4 | tanaka | 40 |
+----+--------+-------+;
-- show tables; でviewの確認
-- drop view xxx; でviewの削除
テーブルの結合
テーブルの結合は内部結合と外部結合がありますが、今回は内部結合のコードを書いておきます
内部結合の場合は主キーと一致するものだけが結合されます。
drop table if exists posts;
create table posts(
id int unsigned primary key auto_increment,
title varchar(255),
body text
);
drop table if exists comments;
create table comments(
id int unsigned primary key auto_increment,
post_id int not null,
body text
);
insert into posts(title, body) values ('title 1', 'body 1');
insert into posts(title, body) values ('title 2', 'body 2');
insert into posts(title, body) values ('title 3', 'body 3');
insert into comments(post_id, body) values (1, 'first comment for post 1');
insert into comments(post_id, body) values (1, 'second comment for post 1');
insert into comments(post_id, body) values (3, 'first comment for post 3');
insert into comments(post_id, body) values (4, 'first comment for post 4');
select * from posts;
select * from comments;
select * from posts join comments on posts.id = comments.post_id;
+----+---------+--------+----+---------+---------------------------+
| id | title | body | id | post_id | body |
+----+---------+--------+----+---------+---------------------------+
| 1 | title 1 | body 1 | 1 | 1 | first comment for post 1 |
| 2 | title 2 | body 2 | 2 | 1 | second comment for post 1 |
| 3 | title 3 | body 3 | 3 | 3 | first comment for post 3 |
+----+---------+--------+----+---------+---------------------------+
last_insert_id()
とりあえずこうなります↓
drop table if exists posts;
create table posts(
id int unsigned primary key auto_increment,
title varchar(255),
body text
);
drop table if exists comments;
create table comments(
id int unsigned primary key auto_increment,
post_id int not null,
body text
);
insert into posts(title, body) values ('title 1', 'body 1');
insert into posts(title, body) values ('title 2', 'body 2');
insert into posts(title, body) values ('title 3', 'body 3');
insert into comments(post_id, body) values (1, 'first comment for post 1');
insert into comments(post_id, body) values (1, 'second comment for post 1');
insert into comments(post_id, body) values (3, 'first comment for post 3');
delete from posts where id = 2;
insert into posts(title, body) values ('new title', 'new body');
insert into comments(post_id, body) values (last_insert_id(), 'first comment for new post');
select * from posts;
select * from comments;
select * from posts join comments on posts.id = comments.post_id;
+----+-----------+----------+----+---------+----------------------------+
| id | title | body | id | post_id | body |
+----+-----------+----------+----+---------+----------------------------+
| 1 | title 1 | body 1 | 1 | 1 | first comment for post 1 |
| 1 | title 1 | body 1 | 2 | 1 | second comment for post 1 |
| 3 | title 3 | body 3 | 3 | 3 | first comment for post 3 |
| 4 | new title | new body | 4 | 4 | first comment for new post |
+----+-----------+----------+----+---------+----------------------------+
データ挿入と更新の時刻
current_timestampを使うことによって自動的に現在時刻でレコードが作成されます。
データの更新時には on update current_timestampを使うとデータを更新したときの日時で日付が更新されます。
create table posts( id int unsigned primary key auto_increment, title varchar(255), body text, created datetime default current_timestamp, updated datetime default current_timestamp on update current_timestamp -- 更新時の日時 );
where句で日付の抽出をするには以下のようにします。
select * from posts where created > '2017-01-01';
日付を加算するには以下のように書けばよいようです。
select created, date_add(created, interval 14 day) from posts; select created, date_add(created, interval 2 week) from posts;
日付のフォーマットを指定
select created, date_format(created, '%W %M %Y') from posts;
データベースの書き出し
データベースの書き出しはmySQLのシェルからぬけておこないmysqldumpを使います
mysqldump -u ユーザー名 -p データベース名 > バックアップファイル名.sql
データを間違えてけしてしまったときなどは、バックアップしたファイルはMySQLのシェルでよみこんであげるだけでデータを復元することができます
source backup.sql

コメント