前提・実現したいこと
1~2日前に触り始めたド素人です。
できるだけ注意しながら書きますが、用語の誤り等があったらすみません。
LivreOffice BASEを使用しています。
練習を兼ねて作ったテーブル・クエリを例に質問しますが、最終的には規模も複雑さももう少し上のものを見据えています。
そもそもテーブルの作り方からして不適切かも知れず、長くなってしまいますが順を追って説明しながら質問させていだだきます。
どうかお付き合いください。
最初に作ったテーブル
学生の評価一覧のようなものをイメージしています。
[テーブル_0]
|ID|名前|住所|得意科目1|評価1|得意科目2|評価2|得意科目3|評価3|
|:--|:--:|:--:|:--:|:--:|--:|
|1|Aさん|東京都|数学|80|化学|90|社会|85|
|2|Bさん|東京都|英語|95|数学|95|||
|3|Cさん|東京都|国語|77|物理|88|英語|99|
ここから、得意科目が「数学」である学生を絞り込みたいとします。
SQL
1SELECT 2"ID", "名前", "住所", "得意科目1", "評価1","得意科目2", "評価2", "得意科目3", "評価3" 3FROM 4"テーブル_0" 5WHERE 6( "得意科目1" = '数学' OR "得意科目2" = '数学' OR "得意科目3" = '数学' )
上記のクエリで
|ID|名前|住所|得意科目1|評価1|得意科目2|評価2|得意科目3|評価3|
|:--|:--:|:--:|:--:|:--:|--:|
|1|Aさん|東京都|数学|80|化学|90|社会|85|
|2|Bさん|東京都|英語|95|数学|95|||
という結果が得られました。結果は満足です。
しかし、今度は「英語」で絞り込みたいと考えたとき「"得意科目○" = '数学' OR…」を3回(本番ではもっと増える予定)書き直さなければならず不便な事と、
正規化、というものを行った方がいいようなので、テーブルを分割しました。
正規化を試みてみました
[メイン]
出席番号 | 名前 | 住所 |
---|---|---|
1 | Aさん | 東京都 |
2 | Bさん | 東京都 |
3 | Cさん | 東京都 |
[得意科目]
ID | 出席番号 | 得意科目 | 評価 |
---|---|---|---|
1 | 1 | 数学 | 80 |
2 | 1 | 化学 | 90 |
3 | 1 | 社会 | 85 |
4 | 2 | 英語 | 95 |
5 | 2 | 数学 | 95 |
6 | 3 | 国語 | 77 |
7 | 3 | 物理 | 88 |
8 | 3 | 英語 | 99 |
そして、[メイン]テーブルの「出席番号」と[得意科目]テーブルの「出席番号」をリレーで結びました。
再び、得意科目が「数学」である学生を絞り込んでみました。
SQL
1SELECT 2"メイン"."出席番号", "メイン"."名前", "メイン"."住所", "得意科目"."得意科目", "得意科目"."評価" 3FROM 4"得意科目", "メイン" 5WHERE "得意科目"."出席番号" = "メイン"."出席番号" AND "メイン"."出席番号" 6IN ( 7SELECT 8"メイン"."出席番号" 9FROM 10"得意科目", "メイン" 11WHERE 12"得意科目"."出席番号" = "メイン"."出席番号" AND "得意科目"."得意科目" = '数学')
結果は
|出席番号|名前|住所|得意科目|評価|
|:--|:--:|:--:|--:|
|1|Aさん|東京都|数学|80|
|1|Aさん|東京都|化学|90|
|1|Aさん|東京都|社会|85|
|2|Bさん|東京都|英語|95|
|2|Bさん|東京都|数学|95|
こうなって欲しい
出席番号、名前、住所、については学生ごとに固定のものであるため1回表示されれば十分であり、無い方がすっきりと見えると考え以下のような出力が欲しいと思いました。
評価は中身が一致してもそれは偶然であり、「略されていたら上と同じ」と考え運用するのではなく明示したいので、値が同じであってもそのまま表示します。
|出席番号|名前|住所|得意科目|評価|
|:--|:--:|:--:|--:|
|1|Aさん|東京都|数学|80|
||||化学|90|
||||社会|85|
|2|Bさん|東京都|英語|95|
||||数学|95|
色々検索してみましたが、行全体が丸々一致した場合に一行のみの表示にする、というのは見つかったのですが、列ごとに重複を確認し1行のみ表示したりしなかったりする方法はみつかりませんでした。
どのようにすれば良いのか、ご教示お願いいたします。
補足など
今回の質問では省きましたが、住所や教科名のようにユニークではなく複数回現れる単語については別にテーブルにわけて、IDで管理するのが良いのではないかと思っています。
「東京都」が「東京府」に改名された場合や、「社会」を「世界史」と表記する事になった際、訂正の箇所が1箇所で済むからです。
冒頭の流れから始まり本質問をする事になった問題へ行き着いたのですが、本題への回答以外にも途中の段階への「テーブルの作り方がおかしい」や「SQLはこうした方がいい」などありましたらご指摘ください。
よろしくお願いします。
解決
yambejpさんに教えていただいたSQLをLibreOffce BASEに対応する形に直す事で希望した結果が得られました。
以下、最終的なSQLです。ありがとうございました。
SQL
1select 2case t4.rank when 1 then t3."num" else Null end as num, 3case t4.rank when 1 then t3."name" else Null end as name, 4case t4.rank when 1 then t3."address" else Null end as address, 5t4."tokui", 6t4."hyoka" 7from "user" as t3 8inner join ( 9select 10t1."ID", 11t1."num", 12t1."tokui", 13t1."hyoka", 14(select count(*)+1 from "tbl" where "num"=t1."num" and "ID"<t1."ID") as rank 15from "tbl" as t1 16inner join "tbl" as t2 17on t1."num"=t2."num" and t2."tokui"='数学' 18) as t4 19on t3."num"=t4."num"
回答1件
あなたの回答
tips
プレビュー