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

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

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

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

SQL

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

Q&A

解決済

1回答

2910閲覧

【SQL】【Oracle】 複数結合、自己結合したテーブルから同じカラムのデータ(中身別)を複数列として抽出したい。

maru-omochi

総合スコア11

Oracle

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

SQL

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

0グッド

1クリップ

投稿2020/11/02 08:15

編集2020/11/02 08:44

前提・実現したいこと

 お疲れ様です。

まずタイトルがうまく要約できず、わかりにくいものとなってしまって申し訳ございません。
もしかするとそもそも不可能であるかもしれないのですが、可能である場合はご教授いただきたいです。
実現したいことは以下です。

■人情報が入っているテーブルからその人名と、その人が休暇を取得した場合の休暇行使日を、取得した休暇別に取得したいです。

・人情報が入っているテーブル=「PERSON」のカラムはそれぞれ、
person_id int primary key
person_code varchar2(10) not null
person_name varchar2(50) not null
で、入っているデータは仮に、

person_idperson_codeperson_name
1001A
2002B
3003C

とします。

・休暇の取得情報が入っているテーブル=「HOLIDAY」のカラムはそれぞれ、
holiday_id int primary key
person_code varchar2(10) not null
holiday_code varchar2(4) not null
holiday_name varchar2(30) not null
used_date char(10 char)
で、入っているデータは仮に、

|holiday_id|person_code|holiday_code|holiday_name|used_date|
|:--:|:--:|:--:|:--:|
|1|001|1000|代休|2020/10/01|
|1|001|2000|有給|2020/10/02|
|1|001|1000|代休|2020/10/03|
|2|002|2000|有給|2020/10/04|
|2|002|1000|代休|2020/10/05|
|3|003|3000|怪我病欠|2020/10/06|
|3|003|3000|怪我病欠|2020/10/07|
|3|003|3000|怪我病欠|2020/10/08|

とします。

これら二つのテーブルを、取得したい休暇情報分自己結合したのち、以下のようなイメージでデータを取得したいと考えております。

person_name代休有休怪我病欠
A2020/10/01nullnull
Anull2020/10/02null
A2020/10/03nullnull
Bnull2020/10/04null
B2020/10/05nullnull
Cnullnull2020/10/06
Cnullnull2020/10/07
Cnullnull2020/10/08

試したこと

以下のようにしてみたのですが当然すべてに合致するものしか取得できずでして、
どのようにしたら上記のような形でデータを取得できるかわかりません。
もし方法があるようでしたらご教授願えるとありがたいです。

SQL(Oracle)

SELECT p.person_name, h1.used_date 代休, h2.used_date 有給, h3.used_date 怪我病欠 FROM PERSON p JOIN HOLIDAY h1 ON p.person_code = h1.person_code JOIN HOLIDAY h2 ON p.person_code = h2.person_code JOIN HOLIDAY h1 ON p.person_code = h3.person_code WHERE h1.holiday_code = '1000' AND h2.holiday_code = '2000' AND h3.holiday_code = '3000'

文章が拙いものとなってしまい、もしかすると伝わりづらいかもしれませんが、何卒よろしくお願い申し上げます。

以上です。

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

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

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

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

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

gentaro

2020/11/02 08:43

回答者に確認してほしいならテーブル作成とデータ挿入のSQLを質問文に書いておいた方が良いです。
maru-omochi

2020/11/02 08:57

ご指摘ありがとうございます。 こちらのご指摘に気が付く前に回答いただきまして解決してしまいました。 次から質問する際にはご指摘内容を踏まえて投稿するように心がけます。 わざわざ拙い投稿を見ていただき、かつご指摘までしていただき感謝です。 お時間を頂戴いたしましてありがとうございました。 また質問した際にはお力添え、ご教授よろしくお願いいたします。
guest

回答1

0

ベストアンサー

結合後のwhere条件にすると、Null考慮も必要になりますから、先に集合を絞るように、結合時に条件指定します。

SQL

1SELECT p.person_name 2 , h1.used_date 代休, h2.used_date 有給, h3.used_date 怪我病欠 3FROM PERSON p 4 left JOIN HOLIDAY h1 5 ON h1.holiday_code='1000' 6 and p.person_code = h1.person_code 7 left JOIN HOLIDAY h2 8 ON h2.holiday_code='2000' 9 and p.person_code = h2.person_code 10 left JOIN HOLIDAY h3 11 ON h3.holiday_code='3000' 12 and p.person_code = h3.person_code

上記をイメージし易いような別な記述にすると、

SQL

1SELECT p.person_name 2 , h1.used_date 代休, h2.used_date 有給, h3.used_date 怪我病欠 3FROM PERSON p 4 left JOIN ( 5 select * from HOLIDAY where holiday_code='1000' 6 ) h1 7 ON p.person_code = h1.person_code 8 left JOIN ( 9 select * from HOLIDAY where holiday_code='2000' 10 ) h2 11 ON p.person_code = h2.person_code 12 left JOIN ( 13 select * from HOLIDAY where holiday_code='3000' 14 ) h3 15 ON p.person_code = h3.person_code

where条件で指定しようとすると、

SQL

1SELECT p.person_name 2 , h1.used_date 代休, h2.used_date 有給, h3.used_date 怪我病欠 3FROM PERSON p 4 left JOIN HOLIDAY h1 5 ON p.person_code = h1.person_code 6 left JOIN HOLIDAY h2 7 ON p.person_code = h2.person_code 8 left JOIN HOLIDAY h3 9 ON p.person_code = h3.person_code 10where (h1.holiday_code='1000' or h1.holiday_code is null) 11 and (h2.holiday_code='2000' or h2.holiday_code is null) 12 and (h3.holiday_code='3000' or h3.holiday_code is null)

投稿2020/11/02 08:48

編集2020/11/02 09:20
sazi

総合スコア25327

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

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

maru-omochi

2020/11/02 08:55

早速の回答ありがとうございます。 凄いです!!思った通りに実行できました。感動しております。 迅速に対応していただいてありがとうございます。本当に感謝です。
sazi

2020/11/02 08:58

まあ、希望の形ではあるんですけど、単にカラムを振り分けただけですから、間を詰めた「クロス集計にしたい」みたいな要望に変わりそうな気はしますが。
maru-omochi

2020/11/02 09:03

クロス集計 というものがあるのですね。 ありがとうございます。早速調べてみることにします。 そもそも回答いただいたような、結合する際にあのように条件を指定する方法があることすら知らず、またたどり着くことができずにいたくらいでして、この内容もしっかり学習しなおして消化したいと思います。 小一時間調べていたのですが、こんなにあっさり回答いただきまして本当に感謝です。 またなにかわからないことに直面した際はお力添えしていただけるとありがたいです。 この度は本当にありがとうございました。
sazi

2020/11/02 09:20

追記しておきました。頑張って下さい。
maru-omochi

2020/11/02 13:26

ほんとになにからなにまでありがとうございます!感謝です。
maru-omochi

2020/11/04 06:23 編集

お疲れ様です。 こちらに記述することではないとは思うのですが、質問として再掲するのもまた申し訳ないと思いこちらにて質問させてください。 上の例で、取得休暇情報テーブル(HOLIDAY)に、 holiday_id  person_code  holiday_code  holiday_name  used_date   1       001      1000        有給   2020/10/02 というデータがもう一つ入った状態で集計をかけると、 person_name    代休      有休    怪我病欠 A        2020/10/01    2020/10/02  null A        2020/10/02    2020/10/02  null A        2020/10/03     null    null のように有休列に同じ日付のデータが取れてしまうのですが、 これを避け、二番目の行の有休がnull となるためには例のクロス集計というものを使えば実現可能でしょうか。 また、最初の行のセレクト文は、システムから動的に項目を抽出される仕様となっており、 そちらに集計関数が使えないという場合にこの問題を解決する方法はありますでしょうか。 ※SELECT p.person_name , h1.used_date 代休, h2.used_date 有給, h3.used_date 怪我病欠の部分。 結合するテーブルを、サブクエリで(SELECT ROW_NUMBER () OVER(PARTITION BY person_name,holiday_code ORDER BY used_date) rowNum のように集計し、それを結合して出すということを試みたのですが、この方法ですと結合条件のholiday_codeに対するデータがない場合、またはholiday_code自体が存在しない場合に正しく集計することができませんでした。 もし実現可能でしたら、実現するために必要な知識を得るためにどのように検索をネットでかけたらよいか教えていただけますでしょうか。。。
sazi

2020/11/04 07:25 編集

コメントした通り詰めるという要望になりましたね。 それぞれの項目で重複なく上に詰めて表示するという事ですよね。 その為には、それぞれを何行目に表示するのかとう情報を作り出して結合する必要があります。 なかなかピンポイントで参考になる情報を見つけるのは厳しいのでないかと思います。 なので、要件を整理して、新たに質問された方が良いかと。
maru-omochi

2020/11/04 07:41

返信ありがとうございます。 承知いたしました。クロス集計というものを使うというのだけでもわかっただけ感謝です。 もうすこし自力で頑張ってみますが、どうにもならないようでしたらこちらでご協力求めるかもしれません。 その時はお手数ですがお手隙の際に回答いただけるとありがたいです。 いつもありがとうございます。
sazi

2020/11/04 07:52

要望が明確では無いですけど、結合する際には、それぞれの行数を求めるだけではなく、それぞれの行数の最大となる行を作成してそこから結合という形になると思います。 頑張ってください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問