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

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

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

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

Q&A

解決済

1回答

2523閲覧

[LibreOffice BASE] 中身が重複した項目の表示を1行のみする、を列ごとに行う方法を教えてください。

退会済みユーザー

退会済みユーザー

総合スコア0

SQL

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

0グッド

0クリップ

投稿2020/07/11 09:48

編集2020/07/13 11:20

前提・実現したいこと

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回(本番ではもっと増える予定)書き直さなければならず不便な事と、
正規化、というものを行った方がいいようなので、テーブルを分割しました。

正規化を試みてみました

[メイン]

出席番号名前住所
1Aさん東京都
2Bさん東京都
3Cさん東京都

[得意科目]

ID出席番号得意科目評価
11数学80
21化学90
31社会85
42英語95
52数学95
63国語77
73物理88
83英語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"

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

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

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

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

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

gentaro

2020/07/11 09:52

> 出席番号、名前、住所、については学生ごとに固定のものであるため1回表示されれば十分であり、無い方がすっきりと見えると考え以下のような出力が欲しいと思いました。 頑張れば無理ではないと思いますが、そもそもSQLはそういう発想で使うものではないです。
退会済みユーザー

退会済みユーザー

2020/07/11 10:18

さっそくの回答ありがとうございます。 >そもそもSQLはそういう発想で使うものではないです。 そうなんですね。 では、SQLはどういうものだと思って使うのが正解なのでしょうか…? また、今回例に挙げたようなデータを管理するには何を用いるのが適切ですか? Excelのオートフィルターだと縦に同一人物の数学、化学、社会、が並んでいてもそれらを一塊の要素として扱うことができないため数学で絞り込むと数学しか表示されず、セルを結合すると並べ替え自体ができなくなってしまい、目的に適った使用はできません。 もし何かよいモノ・方法をご存知でしたらお教えください。
yambejp

2020/07/11 12:04

やってできないことをやるのは無駄ばかりですよ SQLとはアプリケーション側で必要なデータだけ表示するので SQL側では冗長なデータを出すのが正解です
退会済みユーザー

退会済みユーザー

2020/07/11 15:29

SQLではできないというのであれば仕方ないので諦めます。 ただ他にできる見込みのある候補が無いんですよね。残念です。 >SQLとはアプリケーション側で必要なデータだけ表示するので それならばアプリケーションにとって不要なデータは非表示にできそうですね。
yambejp

2020/07/11 15:34

> SQLではできないというのであれば仕方ないので諦めます 回答をよく読んでください。「できない」のではなく「無駄」なので やるべきではないということです。 世の中にはエクセルで芸術的な絵を書く人もいるそうです。 質問者さんだってエクセルで絵を書くなんて無駄がおおくて 馬鹿げてると思うでしょう?つまりは極めればツールが何であれ やれないことはないのです。SQLで絵を書くことだってできます
退会済みユーザー

退会済みユーザー

2020/07/12 06:43

>やってできないことをやるのは無駄 できないことをやろうとするのは(そもそも不可能なのだから)無駄 と解釈してしまっておりました。すみません。 エクセルに例えて「質問です。エクセルで絵を描こうとしているのですが…」といったレベルの質問をしているのが今の私、という事ですね。 ただ、仮に世界に絵を描くことの出来るソフトがエクセルしか存在しないのであれば、馬鹿げた質問とは言えないと思います。 「データを入力した後、求める内容で絞り込んで、結果を表示させる」といった事が可能なソフトは他にあるのでしょうか?あるのであれば教えて頂きたいです。 一応私もLivreOffice BASEでやってみようと思う前に軽く探してみたのですが、家計簿用やギャンブルの収支管理用など、最初から目的が定められたものか、機能が貧弱で実用には足りないソフトしか見つかりませんでした。
退会済みユーザー

退会済みユーザー

2020/07/13 11:27 編集

(このコメントは投稿場所を間違え、削除依頼も上手くいかなかったため、編集で内容を削除しました)
guest

回答1

0

ベストアンサー

とりあえず無理やりやる方法は、ランク付けをして1位を拾うことです

  • 元データ

SQL

1create table user( 2num int primary key, 3name varchar(10), 4address varchar(10)); 5 6insert into user values 7(1,'Aさん','東京都'), 8(2,'Bさん','東京都'), 9(3,'Cさん','東京都'); 10 11create table tbl( 12ID int primary key, 13num int, 14tokui varchar(10), 15hyoka int); 16 17insert into tbl values 18(1,1,'数学',80), 19(2,1,'化学',90), 20(3,1,'社会',85), 21(4,2,'英語',95), 22(5,2,'数学',95), 23(6,3,'国語',77), 24(7,3,'物理',88), 25(8,3,'英語',99);
  • 検索

SQL

1select 2case t4.rank when 1 then t3.num else '' end as num, 3case t4.rank when 1 then t3.name else '' end as name, 4case t4.rank when 1 then t3.address else '' 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 20

投稿2020/07/11 12:29

編集2020/07/11 12:32
yambejp

総合スコア116724

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

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

yambejp

2020/07/11 12:35

> 1~2日前に触り始めたド素人 SQLの基礎学習が足りないように見受けられます。 SQLでやることとアプリ側でやることを判断できるようまずは SQLとは何かをみっちり学習してください
退会済みユーザー

退会済みユーザー

2020/07/11 15:24

回答ありがとうございます。 今日は遅いので明日以降に試してみます。 [元データ]の作成はSQLを使わずにGUIでの作成で大丈夫ですよね? データの入力にSQLを使う事は想定していなかったので…。 >SQLの基礎学習が足りないように見受けられます。 まだ触り始めたばかりですからね。 SQLが私の意図する用途に適うようであれば今後も学習を続けていきたいと思います。 >アプリ側でやること 私の場合ではLivreOffice BASEの側でやる事、という意味でしょうか?
yambejp

2020/07/11 15:29 編集

> [元データ]の作成はSQLを使わずにGUIでの作成で大丈夫ですよね? > データの入力にSQLを使う事は想定していなかったので…。 むしろ質問者が提示するデータです。回答者は想像しながら書いています。 すでにあるテーブルならそのテーブルと該当するカラム名に置き換えて 考えてください > 私の場合ではLivreOffice BASE ごめんなさい、質問者さんの環境がわからないので、それを判断できるのは 質問者さんだけです。 ただ言えるのは、SQLは単体で動作させるものではないので、原則 アプリからミドルウェア経由で実行し、結果もそのままでは役にたたない ので適当な加工をしてクライアントに提示するということ。
退会済みユーザー

退会済みユーザー

2020/07/12 07:43 編集

経過報告です。 回答頂いたSQLを試してみました。 LivreOffice BASEでもSQLでのテーブル作成、データの追加はできるようですが、そのままコピペで貼り付けたところエラーが出て通らなかったので、テーブルはSQLではなくGUIで用意しました。 肝心の検索SQLについてもエラーが出ました。修正しているのですがエラーメッセージが「シンタックスエラー」と表示はされてもどこの部分かは一切教えてくれないレベルのものなので難航しています。 テーブル名等は""でくくる、else ''はelse NULLにする、という所まで判明し、 現在は2回目のfrom(inner join内にあるもの)が認識されていないかのような問題でひっかかっています。 エラーメッセージは「予期しないトークンT1、ステートメントにFROMが必要」です。 asを使用しないパターンは試しましたが改善されませんでした。 この後用事があるので今日はここまでですが、試行錯誤と報告は継続して行っていきたいと思います。 >アプリ すみません、私にはyambejpさんのおっしゃるアプリがどのようなものを指すのかよくわかりませんでした。 「データの入力、欲しい情報を得る為のクエリの作成」という準備が終われば「必要な時に必要な情報を表示させ参考にする」という事ができ、それで私の目的は適います。 そしてその間利用するアプリケーションはLivreOffice BASEのみなのです。(厳密には入力の元データを表示する際にテキストエディタ等を使うと思いますが)
退会済みユーザー

退会済みユーザー

2020/07/12 06:43

追記:修正が必要なのはLivreOffice BASEがおそらく個性的な文法を要求しているからであり、yambejp さんに書いて頂いたSQLが誤っているわけではないと考えています。むしろエクセルで絵を描くようなものだと言いつつ回答してしまうyambejpさんのSQLなので、方言の違いさえ訂正すれば求めていた結果が得られると信じて修正しています。
退会済みユーザー

退会済みユーザー

2020/07/13 11:19 編集

無事、望んだ出力を得る事ができました! FROMが認識されていないかのように見えたエラーについては「t1."ID",」から始まる4行分のカンマを消してしまい「t1."ID"」となっていたのが原因でした。 ””でくくる際に起こったミスだと思いますが、何故"を追加するだけの作業にDelete(BackSpace)キーを押すアクションが混ざったかは自分でも謎です。 成功したSQLを質問文に追記しました。 (ここだとコードで書けないんですね) まだざっくりとしか意味をつかめていないので、まずはこれを題材に勉強していきたいと思います。 回答ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問