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

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

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

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

SQL

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

Q&A

解決済

3回答

2232閲覧

SQL文で、複数のテーブルから複数の条件に合うデータをSELECTしたい

yamekodev

総合スコア17

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

SQL

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

0グッド

0クリップ

投稿2020/08/13 08:16

編集2020/08/14 04:22

オンライン実行環境

下記にて「今のコード」を記入済みのため、動作を試せます。
http://sqlfiddle.com/#!17/a6df3c3/1

現状とやりたいこと

「今のコード」のSELECT文の実行結果は、下記表のようになります。

timeidididnamenamename
2020-08-11111hogepiyofuga
2020-08-11121hogepiyopiyofuga
2020-08-11211hogehogepiyofuga
2020-08-11221hogehogepiyopiyofuga
2020-08-11112hogepiyofugafuga
2020-08-11122hogepiyopiyofugafuga
2020-08-11212hogehogepiyofugafuga
2020-08-11222hogehogepiyopiyofugafuga

しかし、今得たいと思っているのは、下記です。

timeidididnamenamename
2020-08-11111hogepiyofuga
2020-08-11222hogehogepiyopiyofugafuga

つまり、時間とidが同じもののみを結合させて取得したいのですが、
どのようにしたらよいでしょうか。

今のコード

PostgreSQL

1create table meter1 ( 2 observed DATE, 3 id integer, 4 name varchar(10) 5); 6create table meter2 ( 7 observed DATE, 8 id integer, 9 name varchar(10) 10); 11 12create table camera ( 13 recorded DATE, 14 id integer, 15 name varchar(10) 16); 17 18insert into meter1 values('2020-08-11','1', 'hoge'); 19insert into meter1 values('2020-08-11','2', 'hogehoge'); 20insert into meter2 values('2020-08-11','1', 'piyo'); 21insert into meter2 values('2020-08-11','2', 'piyopiyo'); 22insert into camera values('2020-08-11','1', 'fuga'); 23insert into camera values('2020-08-11','2', 'fugafuga'); 24 25SELECT 26 case 27 when meter1.observed is not null then meter1.observed 28 when meter2.observed is not null then meter2.observed 29 when camera.recorded is not null then camera.recorded 30 end as "time", 31 meter1.id, meter2.id, camera.id, 32 meter1.name, meter2.name, camera.name 33FROM 34 meter1 35 FULL OUTER JOIN meter2 ON (meter1.observed = meter2.observed) 36 FULL OUTER JOIN camera ON (meter1.observed = camera.recorded)

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

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

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

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

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

yamekodev

2020/08/13 08:54

ご指摘ありがとうございます。修正しました。
guest

回答3

0

ベストアンサー

idを集約するのに、3つ以上のテーブルでfull outerで行うには無理があります。
一旦全てのIDのリストを取得し、それを元に結合します。

SQL

1SELECT base.id, mybook.name, mybook2.name, mybook3.name, mybook4.name 2FROM ( 3 select id from mybook 4 union select id from mybook2 5 union select id from mybook3 6 union select id from mybook4 7 ) base 8 left join mybook ON base.id = mybook.id 9 left join mybook2 ON base.id = mybook2.id 10 left join mybook3 ON base.id = mybook3.id 11 left join mybook4 ON base.id = mybook4.id

以下は冗長になりますが、unionマージでない分高速であるかもしれません。
特にidに対してindexが設定されているようならさらに。

SQL

1SELECT base.id, mybook.name, mybook2.name, mybook3.name, mybook4.name 2FROM ( 3 select id from ( 4 select id from mybook 5 union all select id from mybook2 6 union all select id from mybook3 7 union all select id from mybook4 8 ) step1 9 group by id 10 ) base 11 left join mybook ON base.id = mybook.id 12 left join mybook2 ON base.id = mybook2.id 13 left join mybook3 ON base.id = mybook3.id 14 left join mybook4 ON base.id = mybook4.id

質問が変更されたので追記

SQL

1SELECT base.id, meter1.observed, meter2.observed, camera.recorded 2FROM ( 3 select observed, id from ( 4 select observed, id from meter1 5 union all select observed, id from meter2 6 union all select recorded, id from camera 7 ) step1 8 group by observed, id 9 ) base 10 left join meter1 ON base.observed= meter1.observed and base.id = meter1.id 11 left join meter2 ON base.observed= meter2.observed and base.id = meter2.id 12 left join camera ON base.observed= camera.recorded and base.id = camera.id

投稿2020/08/13 08:50

編集2020/08/14 05:53
sazi

総合スコア25327

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

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

yamekodev

2020/08/14 05:06

こちらの上のやり方で解決しました。 解決内容は後程追記します。 本当にありがとうございました。 ベストアンサーをつけなおせるか今運営に問い合わせ中です。
sazi

2020/08/14 07:25

解決積みは外せると思います。
yamekodev

2020/09/18 06:41

遅くなり申し訳ございません。 ベストアンサーをこちらの回答に付け替えさせていただきました。 今回はいろいろとありがとうございました。大変助かりました。
guest

0

sazi様の方法を応用して、idでフィルタした結果に対して、where句で時間を指定することで実現できました。
本当にありがとうございました。
http://sqlfiddle.com/#!17/c64c83/14

PostgreSQL

1select 2 base2.id, 3 base2.observed1, 4 base2.observed2, 5 base2.recorded 6from ( 7 select 8 base1.id, 9 meter1.observed AS observed1, 10 meter2.observed AS observed2, 11 camera.recorded, 12 meter1.name, 13 meter2.name, 14 camera.name 15 from ( select id from meter1 16 union select id from meter2 17 union select id from camera 18 ) base1 19 left join meter1 ON base1.id = meter1.id 20 left join meter2 ON base1.id = meter2.id 21 left join camera ON base1.id = camera.id 22 ) base2 23where (base2.observed1 = base2.observed2) 24 AND (base2.observed2 = base2.recorded) 25 AND (base2.recorded = base2.observed1)

以下は自己解決したと勘違いしていたときの内容です。
念のため消さずに残しておきます


要素の名前が違うことをサンプルに入れておらず、正しい質問ができていませんでした。
申し訳ありませんでした。
USINGを使って実現できました。

PostgreSQL

1create table mybook ( 2 observed integer, 3 name varchar(10) 4); 5create table mybook2 ( 6 observed integer, 7 name varchar(10) 8); 9 10create table mybook3 ( 11 recorded integer, 12 name varchar(10) 13); 14 15insert into mybook values('1', 'hoge'); 16insert into mybook2 values('1', 'hogepiyo'); 17insert into mybook2 values('2', 'hogehoge'); 18insert into mybook3 values('2', 'piyo'); 19 20SELECT 21 case 22 when mybook.observed is not null then mybook.observed 23 when mybook2.observed is not null then mybook2.observed 24 when mybook3.recorded is not null then mybook3.recorded 25 end as "time", 26 mybook.name, 27 mybook2.name, 28 mybook3.name 29FROM 30 mybook 31 FULL OUTER JOIN mybook2 USING (observed) 32 FULL OUTER JOIN mybook3 ON (observed = mybook3.recorded)

投稿2020/08/14 02:10

編集2020/08/14 05:10
yamekodev

総合スコア17

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

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

sazi

2020/08/14 02:29

using は同じ項目名の場合に記述を省略できるだけです。 上手くいったというのはテーブル数が減っているからで、質問の前提が変わっただけだと思いますけど。 試しにテーブル数を質問と同様にすると、何も変わっていない事が分かるはずです。
yamekodev

2020/08/14 04:08

すみませんご指摘の通りでした・・・ 改めて、本来やりたいことと近いテーブルを作ったので、質問を編集します。
sazi

2020/08/14 05:48

解決された記述は少し冗長なので、追記しておきました。
yamekodev

2020/08/14 06:15

なるほど、と目からうろこの素晴らしい追記内容でした。 ググっても基本的な内容しかほぼ見つからず困っていましたが、 sazi様のようなきれいな方法を見るととても勉強になります。 何度もありがとうございます。
sazi

2020/08/14 06:19 編集

こちらの解決方法だとwhere条件にNull考慮(結合されない場合)がないので、正しく抽出されなかったりもします。
guest

0

下記でもいいですね。

sql

1SELECT base.id, max(n1) name1, max(n2) name2, max(n3) name3, max(n4) name4 2FROM ( 3 select id, name n1, null n2, null n3 , null n4 from mybook 4 union all select id, null, name, null, null from mybook2 5 union all select id, null, null, name, null from mybook3 6 union all select id, null, null, null, name from mybook4 7 ) base 8 group by id;

投稿2020/08/13 10:39

編集2020/08/13 10:42
hatena19

総合スコア34075

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問