質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

1回答

4194閲覧

INNER JOINからEXISTSに書き換えたい

sendai

総合スコア13

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

1クリップ

投稿2019/01/05 17:34

編集2019/01/06 06:44

前提・実現したいこと

SQL初学者です。
MySQLのサンプルデータベースのひとつであるEmployeesを用いて勉強をしています。

exists文を使って部署(dept_name)毎に現在(to_date="9999-01-01")titleがStaffである人数を集計せよ、という問題を解きたいのですが、existsの使い方がいまいちわかっていないこともあってどのようなSQL文を書けばよいのかわかりません。
内部結合を用いて集計することはできたのですが…(試したことの欄で後述します)

使うテーブル

titlesテーブルとdept_empテーブルはそれぞれ443308レコード、331603レコードあってすべてのレコードをINSERT文の中に記述することはできないため、5レコードのみ記載します。

#####titles

SQL

1CREATE TABLE "titles" 2( 3 "emp_no" INT(11) PRIMARY KEY, 4 "title" VARCHAR(50) PRIMARY KEY, 5 "from_date" DATE PRIMARY KEY, 6 "to_date" DATE 7) 8 9INSERT INTO "titles" 10 ("emp_no", "title", "from_date", "to_date") 11VALUES 12 (10001, "Senior Engineer", "1986-06-26", "9999-01-01"), 13 (10002, "Staff", "1996-08-03", "9999-01-01"), 14 (10003, "Senior Engineer", "1995-12-03", "9999-01-01"), 15 (10004, "Engineer", "1986-12-01", "1995-12-01"), 16 (10004, "Staff", "1995-12-01", "9999-01-01") 17
dept_emp

SQL

1CREATE TABLE "dept_emp" 2( 3 "emp_no" INT(11) PRIMARY KEY, 4 "dept_no" CHAR(4) PRIMARY KEY, 5 "from_date" DATE, 6 "to_date" DATE 7) 8 9INSERT INTO "dept_emp" 10 ("emp_no", "dept_no", "from_date", "to_date") 11VALUES 12 (10001, "d005", "1986-06-26", "9999-01-01"), 13 (10002, "d007", "1996-08-03", "9999-01-01"), 14 (10003, "d004", "1995-12-03", "9999-01-01"), 15 (10004, "d004", "1986-12-01", "1995-12-01"), 16 (10005, "d003", "1989-09-12", "9999-01-01");
departments

SQL

1CREATE TABLE "departments" 2( 3 "dept_no" CHAR(4) PRIMARY KEY, 4 "dept_name" VARCHAR(40) UNIQUE 5) 6 7INSERT INTO "departments" 8 ("dept_no","dept_name") 9VALUES 10 ("d001", "Marketing"), 11 ("d002", "Finance"), 12 ("d003", "Human Resources"), 13 ("d004", "Production"), 14 ("d005", "Development"), 15 ("d006", "Quality Management"), 16 ("d007", "Sales"), 17 ("d008", "Research"), 18 ("d009", "Customer Service");

試したこと

内部結合を用いた集計を行うことには(おそらく)成功しました。

SQL

1SELECT dept_name, COUNT(*) AS num 2FROM 3 (SELECT a.emp_no, a.title, a.to_date, c.dept_name 4 FROM titles a 5 INNER JOIN dept_emp b 6 ON a.emp_no=b.emp_no 7 INNER JOIN departments c 8 ON b.dept_no=c.dept_no) joined 9WHERE title="Staff" AND to_date="9999-01-01" 10GROUP BY dept_name 11ORDER BY dept_name;

実行結果

dept_namenum
Customer Service3902
Development315
Finance3199
Human Resources3416
Marketing3880
Production349
Research3206
Sales9967

補足情報(FW/ツールのバージョンなど)

-> % mysql --version
mysql Ver 8.0.13 for osx10.14 on x86_64 (Homebrew)

初質問なので不足している情報等あってご迷惑をおかけするかもしれませんが、よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sendai

2019/01/06 06:48

的確なご指摘ありがとうございます。 レコード数が多いデータだったのでSQL文で提示するのは向いてないのかな、と思っていましたが、それでもあるに越したことはないですね。 修正致しましたのでぜひご確認ください。よろしくお願いします。
guest

回答1

0

ベストアンサー

こんなところでしょうか。

sql

1SELECT 2 c.dept_name, COUNT(*) AS num 3FROM 4 departments c 5 INNER JOIN 6 dept_emp b ON b.dept_no = c.dept_no 7WHERE 8 EXISTS( SELECT 9 * 10 FROM 11 titles a 12 WHERE 13 a.emp_no = b.emp_no 14 AND a.title = 'Staff' 15 AND a.to_date = '9999-01-01') 16GROUP BY c.dept_name 17ORDER BY c.dept_name;

あと、余談ですが、内部結合のクエリは以下のようにも書き換えられます。
派生テーブルを使わないバージョンです。実際に計測してみたところ、このサイズだとあまり変わらないようでしたが・・・w

sql

1SELECT c.dept_name, COUNT(*) AS num 2 FROM titles a 3 INNER JOIN dept_emp b 4 ON a.emp_no=b.emp_no 5 INNER JOIN departments c 6 ON b.dept_no=c.dept_no 7WHERE a.title="Staff" AND a.to_date="9999-01-01" 8GROUP BY c.dept_name 9ORDER BY c.dept_name;

投稿2019/01/06 13:31

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sendai

2019/01/06 15:08

素早い回答ありがとうございます。 INNER JOINとEXISTSを併用すればよかったんですね…ひとつ勉強になりました。 内部結合に関してもアドバイス非常に助かります!ほぼ独学で勉強しているので、こういったフィードバックはとても新鮮でありがたいです。参考にさせていただきます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問