LoginSignup
0
0

More than 3 years have passed since last update.

MySQLの基本(データベースの操作)3

Posted at

前回の続きです。

データの集計

前回使用したusers_with_teamを用意

create table users (
  id int unsigned primary key auto_increment,
  name varchar(20),
  score float
);

insert into users (name, score) values ('taguchi', 5.8);
insert into users (name, score) values ('fkoji', 8.2);
insert into users (name, score) values ('dotinstall', 6.1);
insert into users (name, score) values ('Tanaka', 4.2);
insert into users (name, score) values ('yamada', null);
insert into users (name, score) values ('tashiro', 7.9);

drop table if exists users_with_team;
create table users_with_team as
select
  id,
  name,
  score,
  case
    when score > 8.0 then 'Team-A'
    when score > 6.0 then 'Team-B'
    else 'Team-C'
  end as team
from users;

-----------------------------------------------------------------------------------

○ NULL以外のレコード数を抽出
select count(score) from users_with_team;

+--------------+
| count(score) |
+--------------+
|            5 |
+--------------+

○ NULL以外のレコード数を抽出
select count(id) from users_with_team;

+-----------+
| count(id) |
+-----------+
|         6 |
+-----------+

○ NULLも含めたレコード数を抽出
select count(*) from users_with_team;

+----------+
| count(*) |
+----------+
|        6 |
+----------+

○ 指定したカラムの合計値を取得
select sum(score) from users_with_team;

+-------------------+
| sum(score)        |
+-------------------+
| 32.19999980926514 |
+-------------------+

select min(score) from users_with_team;

+-------------------+
| min(score)        |
+-------------------+
| 4.199999809265137 |
+-------------------+

○ 指定したカラムの最大値を取得
select max(score) from users_with_team;

+-------------------+
| max(score)        |
+-------------------+
| 8.199999809265137 |
+-------------------+

○ 指定したカラムの平均値を取得
select avg(score) from users_with_team;

+-------------------+
| avg(score)        |
+-------------------+
| 6.439999961853028 |
+-------------------+

○ 指定したカラムで重複を削除し表示
select distinct team from users_with_team;  

+--------+
| team   |
+--------+
| Team-C |
| Team-A |
| Team-B |
+--------+

○ 指定したカラムで重複を削除しレコード数を表示
select count(distinct team) from users_with_team;

+----------------------+
| count(distinct team) |
+----------------------+
|                    3 |
+----------------------+


○ 指定したカラムの合計を指定のカラムごとにグループ化し抽出
select sum(score) from users_with_team group by team;

+-------------------+--------+
| sum(score)        | team   |
+-------------------+--------+
| 8.199999809265137 | Team-A |
|                14 | Team-B |
|                10 | Team-C |
+-------------------+--------+

○ group byに条件を指定するときは、whereではなくhavingを使用する
select sum(score),team from users_with_team group by team having sum(score) > 10;

+------------+--------+
| sum(score) | team   |
+------------+--------+
|         14 | Team-B |
+------------+--------+

viewの作成

○ 抽出条件をテーブルのように扱える。 複雑な抽出条件を何度も使う場合に便利。
○ viewの作成方法
 create view '作成するview名' as select '以降viewにしたい条件'

drop table if exists users;
create table users (
  id int unsigned primary key auto_increment,
  name varchar(20),
  score float
);

insert into users (name, score) values ('taguchi', 5.8);
insert into users (name, score) values ('fkoji', 8.2);
insert into users (name, score) values ('dotinstall', 6.1);
insert into users (name, score) values ('Tanaka', 4.2);
insert into users (name, score) values ('yamada', null);
insert into users (name, score) values ('tashiro', 7.9);

-----------------------------------------------------------------------------------

drop view if exists top3;
create view top3 as select * from users order by score desc limit 3;

○ viewを使用するときは以下のようにしてできる。
select * from top3;
+----+------------+-------+
| id | name       | score |
+----+------------+-------+
|  2 | fkoji      |   8.2 |
|  6 | tashiro    |   7.9 |
|  3 | dotinstall |   6.1 |
+----+------------+-------+

複数のテーブルを扱う

○ ブログのようなものを想定し、postsテーブルが複数のコメントを持つことにする。

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 unsigned not null,  ←どのpostsへのコメントか判断するカラム
  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');


○ 複数のテーブルを紐づけてデータを抽出する方法
  inner join  --2つのテーブルに共通するレコードがあれば抽出

select * from posts inner 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  |
+----+---------+--------+----+---------+---------------------------+


  outer join --2つのテーブルで一致しないデータも含め抽出 どちらのテーブルを軸にするかで構文が異なる

 ・ left outer join
   左に書かれたテーブル(posts)を軸にする。postsに関連するレコードがcommentsになくてもpostsのレコードを表示する。関連するレコードがない場合はNULLで表示される。

select * from posts left outer 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  |
|  2 | title 2 | body 2 | NULL |    NULL | NULL                      |
+----+---------+--------+------+---------+---------------------------+

  ・ right outer join
   右に書かれたテーブル(comments)を軸にする。commentsに関連するレコードがpostsになくてもcommentsのレコードを表示する。関連するレコードがない場合はNULLで表示される。

+------+---------+--------+----+---------+---------------------------+
| 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  |
| NULL | NULL    | NULL   |  4 |       4 | first comment for post 4  |
+------+---------+--------+----+---------+---------------------------+

○ 外部キー制約
  上記の例だと、commentsに外部キー制約を設定することでposts_idが存在しないcommentsレコードを作成しようとするとエラーになる。以下作成方法。
alter table comments add constraint '設定する制約の名前' foreign key (post_id) references posts (id);
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0