データ工学基礎 第四回 -...
Transcript of データ工学基礎 第四回 -...
データ工学基礎
鈴木 優
第四回
SQLによるデータの検索
本日の内容• SQLについて • 実際にデータベースを直接触ってみる • 自由な検索を行うことができるように
• 実際に使ってみる • データベースを直接 • Rails を使って
2
SQLとは?• データベースを操作するための標準的な操作体系 • 表の演算を行う操作が主 • 表の構築,データ入力なども行うことができる • Rails は裏で SQL を生成し操作を行っている • データベースの種類によらず利用することが可能
• SQL をプログラム言語内に埋め込むことが可能 • 各データベースのドライバを利用
3
授業アンケートの表を利用• データベースの中身を見る
4
% mysql -uroot -p Enter password: MariaDB [(none)]> show databases; +-----------------------+ | Database | +-----------------------+ | question_development | | question_test | +-----------------------+ 11 rows in set (0.01 sec)
MariaDB [(none)]> use question_development; Database changed
MariaDB [question_development]> show tables; +--------------------------------+ | Tables_in_question_development | +--------------------------------+ | ar_internal_metadata | | inquiries | | inquiries_students | | schema_migrations | | students | +--------------------------------+ 5 rows in set (0.00 sec)
mysql コマンドでデータベースへデータベースの一覧
データベースへ入る
表の一覧
(参考)選択演算
5
θ-選択演算リレーション R(A1,A2, ... ,An)において AiとAjがθ-比較可能であるとするとき,Ai
とAj上のθ-選択 -これをR[AiθAj]と表す - は次のように定義されるリレーション
である
<latexit sha1_base64="fHGzIub+9L/8JlXfb61bC6uONUU=">AAACpXichVFNT9tAEH2YtkD6QaAXJC6rRtCeonEvRUhIgV64IEEgASmOLNssYcGxLXsTBCl/oH+AAyeQAFX9GVw49EolfkLVI5V66YGx46pqUduxvDvz9r3Zt7tu5KtEE90MGIMPHj4aGh4pPH7y9NlocWy8noSd2JM1L/TDeMN1EumrQNa00r7ciGLptF1frru7b9P19a6MExUGa3o/ks220wrUlvIczZBdrFQb87YSlt6W2hHz9k5TzAmrJ7R4J7SlAlEV1p7cbEmhU2LzJzOtmGsd2sUSlSkLcT8x86SEPJbD4gUsbCKEhw7akAigOffhIOGvAROEiLEmeozFnKlsXeIQBdZ2mCWZ4TC6y2OLq0aOBlynPZNM7fEuPv8xKwWm6Jo+0C1d0Uf6Qj/+2quX9Ui97PPs9rUyskffT6x+/6+qzbPG9i/VPz1rbGEm86rYe5Qh6Sm8vr57cHS7Olud6k3TKX1l/yd0Q5d8gqD7zTtbkdVjFPgBzD+v+35Sf102qWyuUKmykD/FMCbxAq/4vt+ggkUso8b7nuMTrvHZeGksGWtGvU81BnLNc/wWhn0H1nugbg==</latexit>
商品番号 原価 売価刺身 600 500豆腐 90 75卵 95 100
商品
商品番号 原価 売価刺身 600 500豆腐 90 75
商品[原価>売価]
商品番号 原価 売価刺身 600 500
商品[原価>500]
SELECT 文
• 全学生を表示せよ • SELECT * FROM STUDENTS;
• 全質問を表示せよ • SELECT * FROM INQUIRIES;
• 質問だけを全部表示せよ • SELECT ENTRY FROM INQUIRIES;
6
SELECT [属性名] FROM [表名];
[表名]の中から[属性名]に含まれるデータだけを表示せよ
(全ての属性の場合は属性名を * とする)
セミコロンを忘れない
出力順は一定ではないことに注意 (必ずしも毎回同じ順に出てくるわけではない)
SELECT 文(条件付き)
• 男性の学生を表示せよ • SELECT * FROM STUDENTS WHERE GENDER = ‘男';
• 学籍番号が101番から105番の学生を表示せよ • SELECT * FROM STUDENTS WHERE REG_NUM >= 101 AND REG_NUM <= 105;
• SELECT * FROM STUDENTS WHERE REG_NUM BETWEEN 101 AND 105
• 学籍番号が奇数の学生をIDと名前だけ表示せよ • SELECT ID, NAME FROM STUDENTS WHERE REG_NUM % 2 = 1;
7
SELECT [属性名] FROM [表名] WHERE [条件];
[表名]の中から[条件]を満たす,[属性名]に含まれるデータだけを表示せよ
SELECT 文(順序)
• 学生を学籍番号順に表示せよ • SELECT * FROM STUDENTS ORDER BY REG_NUM;
• 学生を学籍番号の降順 • SELECT * FROM STUDENTS ORDER BY REG_NUM DESC;
8
SELECT [属性名1] FROM [表名] ORDER BY [属性名2] (DESC);
[表名]の中から[属性名1]に含まれるデータだけを[属性名2]の昇順で表示せよ
SELECT 文(グループ)
• 学生ごとに回答した数を出力したい • SELECT student_id, COUNT(answer) FROM INQUIRIES_STUDENTS GROUP BY student_id;
9
SELECT [属性名1] FROM [表名] GROUP BY [属性名2];
[表名]の中から[属性名2]でグループ化して出力
SELECT [属性名1] FROM [表名] GROUP BY [属性名2] HAVING [条件];
[表名]の中から[属性名2]でグループ化したもののうち[条件]を満たすものを出力
• 学生ごとに回答した数を出力したい(回答数が3個以上のもの) • SELECT student_id, COUNT(answer) FROM INQUIRIES_STUDENTS GROUP BY student_id HAVING COUNT(answer) >= 3;
(参考)内部結合 (Inner Join)
10
A1 A2a 1b 2c 3
B1 B21 e1 f2 g2 h4 i4 j
R S
A1 A2 B1 B2a 1 1 ea 1 1 fb 2 2 gb 2 2 h
R[A2=B1]S
A2とB1双方に対応するカラムが無い場合には無視する
結合
• 学生表と回答表を結合せよ • SELECT * FROM STUDENTS, INQUIRIES_STUDENTS;
• 学生表,回答表,質問票をすべて結合せよ • SELECT * FROM STUDENTS, INQUIRIES_STUDENTS, INQUIRIES;
11
SELECT [属性名] FROM [表名1],[表名2];
[表名1]と[表名2]を結合し[属性名]に含まれるデータだけを表示せよ
結合 (JOIN)
• 学生表と回答表のうち学生.IDと回答.student_idが同じものを結合して表示せよ • select * from students, inquiries_students where students.id = inquiries_students.id;
• select * from students join inquiries_students where students.id = inquiries_students.id;
12
SELECT [属性名] FROM [表名1] JOIN [表名2] ON [条件];
SELECT [属性名] FROM [表名1],[表名2] WHERE [条件];
[表名1]と[表名2]を結合し[属性名]に含まれるデータのうち[条件]を満たすものだけを表示せよ
自己結合 (JOIN)
• 学生の総当たりの表を作成せよ • select A.name, B. name from students A, students B;
• 総当たりの表のうち二人は別の人となるように • select A.name, B.name from students A, students B where A.name != B.name;
13
SELECT [属性名] FROM [表名1] JOIN [表名2] ON [条件];
SELECT [属性名] FROM [表名1],[表名2] WHERE [条件];
[表名1]と[表名2]を結合し[属性名]に含まれるデータのうち[条件]を満たすものだけを表示せよ
同じ表を結合することができる
SQLの中にSQLを書く
• 何らかの質問に一度でも「はい」と答えた学生の名前を出力せよ • select distinct name from students where id in (select student_id from inquiries_students where answer = ‘はい’);
14
SELECT [属性名] FROM [表名1] WHERE [属性名] IN [SQL文]
SQL文の出力を条件文の中に入れる
和
• 学生の名前と質問の一覧を合わせて表示 • select name from students union select entry from inquiries;
15
SELECT [属性名1] FROM [表名1] UNION SELECT [属性名2] FROM [表名2];
[属性名1]に含まれるデータと[属性名2]に含まれるデータの和
差SELECT [属性名1] FROM [表名1] WHERE NOT IN (SELECT [属性名2] FROM
[表名2]);
[属性名1]に含まれるデータであり,かつ[属性名2]に含まないデータ
• 学生の名前のうち田中二郎でない名前 • select name from students where name not in ( select name from students where name != ‘田中二郎’);
SQLのminusやexceptがMySQLでサポートされていないのでサブクエリで代替
制限 (LIMIT)
• 学生を3人表示せよ • select * from students limit 3;
• サブクエリの中では LIMITが使えない(未実装)
16
SELECT [属性名] FROM [表名] LIMIT [数値];
[表名]の中から[属性名]に含まれるデータを [数値]個表示せよ
問題
初級編1. 学生の一覧を出力せよ
2. 質問の一覧を出力せよ
3. 質問IDが1である質問に「はい」と答えた数を出力せよ
4. 学生二人のペア候補を全て出力せよ
5. 学生IDが2である学生の回答を質問IDの昇順に出力せよ
18
上級編1. 各学生ごとに,回答した質問の数を出力せよ
2. 各質問ごとに,回答した学生の数を出力せよ
3. 学生は全ての質問に答えなければならないが,いくつかの質問に
しか答えていない状況である.学生ごとに,答えていない質問を
すべて出力せよ
19
Railsでデータを問合せ
コントローラでモデルを使って問合せ• 主な二つの方法 • Active Record を使った問合せ • ruby で問合せを書く→Rails 側で SQLに変換 • データベースに合った記述に自動的に変換してくれる • 非効率なSQLになる可能性もある
• SQLを使った問合せ • SQLを直接Railsのアプリケーションに記述 • データベースに依存する場合がある • SQLが非効率かどうかは書く人に依存する
21
Active Record による問合せ• http://localhost:3000/students/ の内容を変更してみる • コントローラは app/controllers/students.html.erb • index は 6-8行目 • @students = Student.all の部分を変更していく
• モデル.where(条件) • 学籍番号901の人だけを表示 • @students = Student.where(reg_num: 901)
• 田中三郎さんだけを表示 • @students = Student.where(name: ‘田中三郎’)
• 学籍番号901で名前が田中三郎さんを表示 • Student.where(reg_num:901, name: ‘田中三郎’)
22
SQLによる問合せ• 同じように変更する
• モデル.find_by_sql(SQL文字列) • 学籍番号901の人だけを表示 • Student.find_by_sql(‘select * from students where reg_num = 901’)
• 田中三郎さんだけを表示 • Student.find_by_sql(‘select * from students where name = ‘田中三郎’)
• 学籍番号901で名前が田中三郎さんだけを表示 • Student.find_by_sql(‘select * from students where reg_num = 901 and name = ‘田中三郎’)
23
今回のまとめ• SQLによるデータベースへの問合せ • Railsによる問合せ
24
次回予告• データベース設計について • 正規形
25