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

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

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

Oracleは、米オラクルが取り扱うリレーショナルデータベース管理システムです。メインフレームからPCまで、多様なプラットフォームに対応しています。

SQL

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

Q&A

解決済

2回答

2292閲覧

OracleSQLの階層問い合わせ:3層以上あるときの最上位層情報を持つ行の重複を解消したい。

Ryuichi_Yamamot

総合スコア11

Oracle

Oracleは、米オラクルが取り扱うリレーショナルデータベース管理システムです。メインフレームからPCまで、多様なプラットフォームに対応しています。

SQL

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

0グッド

1クリップ

投稿2017/10/19 06:41

編集2017/10/22 08:02

###前提・実現したいこと
以下の二つのカラムを持つテーブルがあります。
Course:大学の講義のコードと講義名を持つ
科目コード、コース名

Prereq:必修科目(ある講義を受ける前に取らないといけない講義)を持つ講義と、その必修科目を表すコードを持つ。(ツリー型)
科目コード、必修科目コード

Oracle SQLで階層問い合わせ(Start with, Connect by prior)を使うことで、必修科目を持つ講義に関しては下記のように、必修科目を持たない講義に関してはPrerequisite(s)に"-"ハイフンを表示し、それらを結合した結果を表示したいと思っています。Prerequisites(2)では、最初に親(一番最初に受けないといけない科目)が来るようにする必要があります。

###発生している問題・エラーメッセージ
必修科目を持つ講義に関して、今の自分のコードでは、3層以上あるときに最上位層の科目が複数表示されてしまいます。(例:COSC3320 /COSC1310 と COSC5234 /COSC1310/COSC3320は残して、COSC3380 /COSC3320を削除したいが、今はすべてが表示されている)。

###試したこと
最初のほうに試したことを忘れてしまいましたが、覚えている限り書きます。
prior を消す。
start with句を単純な条件で試してみる。 例えばstart with prq.course_number in ('COSC5234', 'COSC3320')で実行してみましたが、同じ症状が出ました。

###補足情報(言語/FW/ツール等のバージョンなど)
Oracle 12c を使ってOracle Developer上で動かしています。
ほかに何か必要な情報があれば、すぐに用意します。

自分なりに調べて書いていろいろ試みたのですが、どうしてもうまくいきません。。。どうがよろしくお願いいたします。

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

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

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

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

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

guest

回答2

0

ベストアンサー

下記としてみましたが、いかがでしょうか。
ただし、必修科目(prereq)として、さらにその前提として複数の必修科目を持つ科目を指定した場合に、SYS_CONNECT_BY_PATHで取得する都合上、講義コード(course_number)が重複して出力されてしまうようです。

sql

1SELECT 2 course_number "Course", 3 COALESCE(REPLACE(LISTAGG(prereq, '/') WITHIN GROUP (ORDER BY prereq ASC NULLS LAST), '//', ''), '-') "Prerequisite(s)", 4 course_name "Course Name" 5FROM 6( 7 SELECT 8 c.course_number , 9 CASE 10 WHEN SYS_CONNECT_BY_PATH(p.prereq, '/') = '/' 11 THEN '' 12 ELSE SYS_CONNECT_BY_PATH(p.prereq, '/') 13 END prereq, 14 c.course_name 15 FROM course c 16 LEFT JOIN prereq p ON c.course_number = p.course_number 17 START WITH p.prereq IS NULL 18 CONNECT BY PRIOR c.course_number = p.prereq 19) t 20GROUP BY course_number, course_name 21ORDER BY 1;

投稿2017/10/19 08:42

編集2017/10/22 09:04
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

Ryuichi_Yamamot

2017/10/19 09:01 編集

ありがとうございます!!まだ途中とのことですが、ちょっと複雑なSQLになりそうですね。。。自分でもこれを参考に試してみますが、完成お待ちしております! また、なぜ私の元のコードではうまくいかないのか、もしご存知でしたら解説いただけると大変ありがたく思います。
Ryuichi_Yamamot

2017/10/20 07:31 編集

suyamaさん、ありがとうございます!いま私の環境でいろいろ調整しながら試しています。結果はもう少々お待ちくださいませm(_ _)m
Ryuichi_Yamamot

2017/10/22 07:37 編集

解けました!!!大変感謝です! 以下、改善した点と、私の元のコードがうまくいかなかった原因についてまとめます。 1 一番外側のListaggは不要でした。よってGroup byも不要でした。行の数は変わらない(Inline selectですでにAggreateされている)ので。 2 levelに関する実装をしました。 >>>元のコードがうまくいかなかった原因 深く追ったわけではありませんが(実行計画もまだ勉強してないので。。。)、おそらくStart with で副問い合わせを使ったのが原因と思います。副問い合わせの中では階層の中間のコードも含んでいるので、それが悪さをしていたように思います。 事実、「試したこと」でも述べたように、start with prq.course_number in ('COSC5234', 'COSC3320')とシンプルな形で実行した時も同様の問題が発生していました。 以上です!!ありがとうございました!
guest

0

http://www.oracle.com/technetwork/jp/articles/otnj-sql-image6-1352149-ja.html#h

where connect_by_IsLeaf = 1 (葉だけ抽出する) を入れてみるのはどうでしょうか。

投稿2017/10/20 07:28

SugiTK

総合スコア495

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

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

Ryuichi_Yamamot

2017/10/20 09:37

コメントありがとうございます!確かにconnect_by_IsLeafも使えそうですね。(別ソースhttps://codezine.jp/article/detail/2696)。 ただ個人的には、3層以上ある場合は、1層目と2層目も区別できるLevelのほうが便利なような気がしました。 上記URLのシリーズの中に、階層問い合わせに関する他の関数がいろいろ紹介されていたので、見てみようと思います。
SugiTK

2017/10/20 10:18

Google先生とかこことかに聞くのではなくて、マニュアルからたどる癖をつけておくと実力になると思います。
Ryuichi_Yamamot

2017/10/20 10:46

アドバイスありがとうございます。マニュアル=OracleのDocumentationのことと思いますが、おっしゃる通り、あの長く小難しいページはいつもスルーしてみました。すぐにマニュアルだけで問題を解決していくのは難しいですが、少しずつ読み込んでいくように努力します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問