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

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

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

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

Q&A

3回答

3709閲覧

SQLのコードを短くしたい

sky.user.

総合スコア15

SQL

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

0グッド

1クリップ

投稿2018/07/20 06:26

前提・実現したいこと

お世話になっております。
SQLで苦戦しております。
自分でコードを書いて、動くことを確認したのですが、冗長に感じています。。。
短くする(※アルゴリズムの変更も含む)ことは可能でしょうか?

以下問題のテーブル(studentとtest)とレコードの図です。

student

id student_name


001 杏子
002 明日香
003 亜紀
004 小鳥
005 柚子
006 葵


test

id_subject result


001国語 65
002国語 70
002数学 50
003生物 100
003倫理 45
003数学 75
004物理 30
006地学 55


発生している問題・エラーメッセージ

コードは動くが、冗長に感じるため短くしたい

問題:1番高い点数を持つ生徒名とその点数、1番低い点数を持つ生徒名とその点数を出すSQL

結果


|小鳥 | 30 |


|亜紀 | 100 |


該当のソースコード

SQL

1SELECT s.id,t.result 2FROM student s 3JOIN test t 4ON s.id=SUBSTR(t.id_subject,1,3) 5LEFT JOIN(SELECT MAX(t.result)AS value FROM test t)max 6ON max.value=t.result 7LEFT JOIN(SELECT MINX(t.result)AS value FROM test t)min 8ON min.value=t.result 9WHERE max.value IS NOT NULL OR min.value IS NOT NULL;

試したこと

データを抜き出せることは確認しました。

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

SQLplus, Oracle11g

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

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

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

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

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

yambejp

2018/07/20 06:29

id_subjectがstudentのidと教科を連結したようなデータになっていますがマストですか?カラムを分けていいならもっと楽だと思いますが・・・
sky.user.

2018/07/20 06:48

ご回答ありがとうございます。そうですね…今のテーブル、レコードがこの形なのでこのまま使いたいと思っています。
yambejp

2018/07/20 06:51

「このまま使いたい」というのでとめはしませんが、パフォーマンスは期待できませんのであしからず。回答付けておきました
Orlofsky

2018/07/20 07:08

yambejpさんと同意見です。データが増えるとパフォーマンスは極端に悪くなりますし、今後も複雑なSQLを書き続けなければなりません。わたしの部下ならプロジェクトから外すか、殴り倒してでも直させます。
sazi

2018/07/20 07:25

普通科目ごとの最高/最低の点数だと思いますけど、科目によらず最高/最低なんでしょうか?
Orlofsky

2018/07/20 07:32

[Oracle]タグを使いしてください。
guest

回答3

0

図でイメージするOracleのSQL全集 第3回 分析関数
https://blogs.oracle.com/otnjp/oracle-sql-image-003
を見ながら作ってみました :-)

sql

1with student(id,student_name) as( 2select '001','杏子' from dual union 3select '002','明日香' from dual union 4select '003','亜紀' from dual union 5select '004','小鳥' from dual union 6select '005','柚子' from dual union 7select '006','葵' from dual), 8test(id_subject,result) as( 9select '001国語', 65 from dual union 10select '002国語', 70 from dual union 11select '002数学', 50 from dual union 12select '003生物',100 from dual union 13select '003倫理', 45 from dual union 14select '003数学', 75 from dual union 15select '004物理', 30 from dual union 16select '006地学', 55 from dual), 17tmp as( 18select id_subject,result 19from (select id_subject,result, 20 min(result) over() as minResult, 21 max(result) over() as maxResult 22 from test) 23 where result in(minResult,maxResult)) 24select a.id,a.student_name,b.result 25 from student a Join tmp b 26 on a.id = substr(b.id_subject,1,3); 27 28| ID | STUDENT_NAME | RESULT | 29|-----|--------------|--------| 30| 003 | 亜紀 | 100 | 31| 004 | 小鳥 | 30 | 32

投稿2018/07/21 11:43

編集2020/07/26 08:37
AketiJyuuzou

総合スコア1147

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

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

0

1つ列には1つ意味しか持たせてはならない、というテーブル設計の基本を守らないからです。
testテーブルのid_subjectにstudent.id と教科名を合体させているのが敗因です。

SQL

1CREATE TABLE SUBJECTS -- 教科テーブル 2 ( 3 SUBJECT_ID NUMBER(3) NOT NULL -- 教科ID 4 , SUBJECT_NAME VARCHAR2(32) NOT NULL -- 教科名 5 , CONSTRAINT SUBJECTS_PK PRIMARY KEY(SUBJECT_ID) USING INDEX 6 ) ;

test テーブル(生徒履行テーブル)には STUDENT.ID, SUBJECT_ID, RESULT を持てば、SELECT文は自分で直せるかと。

テーブル定義はCREATE TABLEで載せると解決が早いです。
テーブル名や列名のネーミングには気を使いましょう。

投稿2018/07/20 06:48

Orlofsky

総合スコア16415

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

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

0

oracleで有効かどうかはわかりませんが一応こんなかんじで

SQL

1select t2.student_name,t1.result from test as t1 2inner join student as t2 3on substr(t1.id_subject,1,3)=t2.id 4where not exists(select 1 from test having t1.result>min(result)) 5or not exists(select 1 from test having t1.result<max(result))

ただし最高点や最低点が2人以上いるときにどうしたいかなど
仕様をつめないといけません

調整

SQL

1select t2.student_name,t1.result from test as t1 2inner join student as t2 3on substr(t1.id_subject,1,3)=t2.id 4where not exists(select 1 from test 5having t1.result>min(result) 6and t1.result<max(result))

投稿2018/07/20 06:50

編集2018/07/20 07:24
yambejp

総合スコア114775

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

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

sazi

2018/07/20 07:19

副問合せのhavingでの条件を最大または最小にしたら、副問合せを一つに纏められそう
sazi

2018/07/20 07:22

あれ、副問合せにidでの条件が無いですね
sazi

2018/07/20 07:23

あ、最高点と最低点の生徒か。普通学科ごとな気がしますけどね。
yambejp

2018/07/20 07:25

saziさんにご指摘いただき、よく考えればandでまとめられましたので追記しました
sazi

2018/07/20 07:28 編集

t1.result=min(result) or t1.result=max(result) では?
yambejp

2018/07/20 07:29

ああ、そうですね・・・
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問