🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

SQL

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

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

データベース設計

データベース設計はデータベースの論理的や物理的な部分を特定する工程です。

Q&A

解決済

1回答

902閲覧

【DB】教科の持つ科目数と生徒の受講した科目数が一致しない場合SELECTしない

UShow

総合スコア4

SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

SQL

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

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

データベース設計

データベース設計はデータベースの論理的や物理的な部分を特定する工程です。

0グッド

0クリップ

投稿2021/02/25 05:36

編集2021/02/25 06:25

前提・実現したいこと

以前ご質問した内容【DB】不合格が1科目でもある場合抽出されないようにしたいの発展問題です。

生徒の受講した科目が、教科が含む科目数に一致しない場合SELECTせず
かつ教科内の科目で一つでも不合格な科目がある場合、その教科はSELECTしない(こちらは解決済)

この条件の教科履歴のVIEWを作りたいです。

まず、テーブルが2つあります。

生徒の受講した教科履歴のテーブル(Course_history)

log_idnamecourse_idcourse_namesubject_idsubject_nameis_passed
1太郎1理科1化学1
2太郎1理科2物理0
3太郎1理科3生物1
4花子1理科1化学1
5花子1理科2物理1
6花子1理科3生物1
7太郎2数学1数A1
8太郎2数学2数B1
9太郎2数学3数C1
10花子2数学1数A1

教科と科目の関係を表すテーブル(Course_Subject)

idcourse_idcourse_namesubject_idsubject_name
11理科1化学
21理科2物理
31理科3生物
42数学1数A
52数学2数B
62数学3数C

発生している問題

教科内の科目で一つでも不合格な科目がある場合、その教科はSELECTしないは以下のクエリで解決しています。

SELECT log_id, t1.name, t1.course_id, t1.subject_id, t1.subject_name, t1.is_passed FROM Course_history AS t1 INNER JOIN (SELECT name, course_id FROM Course_history GROUP BY name, course_id HAVING COUNT(course_id) = SUM(is_passed)) AS t2 ON t2.name = t1.name AND t2.course_id = t1.course_id

これで結果が
|log_id|name|course_id|course_name|subject_id|subject_name|is_passed|
|:--:|:--:|:--:|:--:|:--:|:--:|
|4|花子|1|理科|1|化学|1|
|5|花子|1|理科|2|物理|1|
|6|花子|1|理科|3|生物|1|
|10|花子|2|数学|1|数A|1|
|7|太郎|2|数学|1|数A|1|
|8|太郎|2|数学|2|数B|1|
|9|太郎|2|数学|3|数C|1|

になります。

それで今回はさらに生徒の受講した科目が、教科が含む科目数に一致しない場合SELECTしない、ようにしたいので、上表のlog_id 10が省かれそれ以外が抜き出されるような条件を作りたいです。

サンプルデータ

CREATE TABLE Course_history ( log_id INT NOT NULL, name NVARCHAR(5) NOT NULL, course_id INT NOT NULL, course_name NVARCHAR(5) NOT NULL, subject_id INT NOT NULL, subject_name NVARCHAR(5) NOT NULL, is_passed INT NOT NULL) INSERT INTO Course_history VALUES (1,'太郎',1,'理科',1,'化学',1) INSERT INTO Course_history VALUES (2,'太郎',1,'理科',2,'物理',0) INSERT INTO Course_history VALUES (3,'太郎',1,'理科',3,'生物',1) INSERT INTO Course_history VALUES (4,'花子',1,'理科',1,'化学',1) INSERT INTO Course_history VALUES (5,'花子',1,'理科',2,'物理',1) INSERT INTO Course_history VALUES (6,'花子',1,'理科',3,'生物',1) INSERT INTO Course_history VALUES (7,'太郎',2,'数学',1,'数A',1) INSERT INTO Course_history VALUES (8,'太郎',2,'数学',2,'数B',0) INSERT INTO Course_history VALUES (9,'太郎',2,'数学',3,'数C',1) INSERT INTO Course_history VALUES (10,'花子',2,'数学',1,'数A',1)

Course_Subject

1CREATE TABLE Course_Subject ( 2id INT NOT NULL, 3course_id INT NOT NULL, 4course_name NVARCHAR(5) NOT NULL, 5subject_id INT NOT NULL, 6subject_name NVARCHAR(5) NOT NULL,) 7INSERT INTO Course_Subject VALUES (1,1,'理科',1,'化学') 8INSERT INTO Course_Subject VALUES (2,1,'理科',2,'物理') 9INSERT INTO Course_Subject VALUES (3,1,'理科',3,'生物') 10INSERT INTO Course_Subject VALUES (4,2,'数学',1,'数A') 11INSERT INTO Course_Subject VALUES (5,2,'数学',2,'数B') 12INSERT INTO Course_Subject VALUES (6,2,'数学',3,'数C')

試したこと

ひとまず、Course_Subjectの教科が含む科目数は3ずつというのはわかります。
この本来の教科が持つ科目数COUNT(course_id) = ユーザーの受講した教科のCOUNT(course_id)になればいいと思うのですが…
そのような条件もどこに入れたらいいのかわかっていません。

SELECT COUNT(course_id) AS count_course FROM Course_Subject GROUP BY course_id
course_idcount_course
13
23

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

SQL Serverになります。

何卒宜しくお願い致します。
ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答1

0

ベストアンサー

単純に条件を追加するだけなら、Course_Subjectの履修科目数を条件に追加すれば良いかと。

SQL

1SELECT log_id, 2 t1.name, 3 t1.course_id, 4 t1.subject_id, 5 t1.subject_name, 6 t1.is_passed 7FROM Course_history AS t1 8 INNER JOIN ( 9 SELECT crs.name, crs.course_id 10 FROM Course_history crs 11 inner join ( 12 select course_id, count(*) as subject_count 13 from Course_Subject 14 group by course_id 15 ) sbj 16 on crs.course_id=sbj.course_id 17 GROUP BY crs.name, crs.course_id, subject_count 18 HAVING COUNT(crs.subject_id) = SUM(is_passed) 19 and COUNT(crs.subject_id)!=subject_count 20 ) AS t2 21 ON t2.name = t1.name AND t2.course_id = t1.course_id

結合するなら、HAVINGではなくて、結合後にwhere条件で指定するようにした方が可読性は上がると思います。

投稿2021/02/25 06:19

編集2021/02/25 06:24
sazi

総合スコア25327

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

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

UShow

2021/02/25 07:09

sazi様 お世話になっております!この度はご回答ありがとうございます。 INNER JOIN を入れ子にすることでGROUP BYしたものを繋げられるとは、知りませんでした 頂いたご回答を参考にさせて頂いたところ、無事解決致しました! この度は誠にありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問