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

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

ただいまの
回答率

90.51%

  • SQL

    2460questions

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

  • PostgreSQL

    1097questions

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

[PostgreSQL][9.6.x]VIEW生成用SQLとVIEWのレコード数が相違する

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 162

sllmejacob

score 64

 現象

あるテーブルAに複数のテーブル(B,C,D)をleft joinしてviewを作っているのですが、
view生成用SQLを実行すると結果として4レコード返ってくる(想定通り)のに対して、
同じSQLで作成したviewを参照すると2レコードになってくる現象が起きており困っています。

識者の方、この現象に対して心当たりがありましたら御教授をお願いいたします:bow_tone1:

 view生成用SQL概要

    select ...(略)
      from table_a as a
 left join table_b as b
        on a.b_id = b.id
       and b.deleted = false
 left join table_c as c
        on a.c_id = c.id
       and c.deleted = false
 left join table_d as d
        on a.d_id = d.id
       and d.deleted = false
;
  • このSQLを直接実行:4件
  • このSQLのVIEW参照:2件 ←???

 別記事項

left joinで参照する先のテーブルにはon句で一致するデータがない場合があります。
また、on句の中にandでdeletedというフラグがfalseであることを指定しています。

私としては(普通に?)、条件合致しないカラムはnullで結合されてくることを期待しているのですが…。

 コンソール(件数確認)

m

test-> ;
 count
-------
     4
(1 行)


test=> select count(*) my_view;
 count
-------
     2
(1 行)

 version:9.6.x

 補足(解決)情報

以下のようにleft join箇所で副問い合わせを行うようにして、
そこにonで結合を行うことで希望のレコードも抽出できました。

直接left join onで記載すると、主レコードの結合キーがnullの場合などに抽出が利かなくなるようです。

訂正依頼&御回答いただいた皆様、ありがとうございました。

    select ...(略),
           b.column1,
           c.column1,
           d.column1
      from table_a as a
 left join (
    select table_b.id,
           table_b.column1,
           ...
      from table_b
     where deleted = false
           ) b
        on a.b_id = b.id
 left join (
    select table_c.id,
           table_c.column1,
           ...
      from table_c
     where deleted = false
           ) c
        on a.c_id = c.id
 left join (
    select table_d.id,
           table_d.column1,
           ...
      from table_d
     where deleted = false
           ) d
        on a.d_id = d.id
;
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • sazi

    2018/05/19 10:38

    提示されている情報以外のところに問題がありそうです。再現可能となる情報を追加してください。

    キャンセル

  • sllmejacob

    2018/05/19 15:08

    saziさん コメントいただきありがとうございます。クエリを見直して解決できました。質問を改修して現象を再現できるようにしておきたいと思います。ありがとうございました。

    キャンセル

回答 4

+1

解せないので、検証しましたが、やはりそのような事象は発生しませんでした。

構築

create table table_a(id int not null, b_id int, item text, CONSTRAINT table_a_key PRIMARY KEY (id));
insert into table_a values (1,1,'item1'),(2,2,'item2'),(3,3,'item3'),(4,Null,'item4');
create table table_b(id int not null, item text, deleted boolean, CONSTRAINT table_b_key PRIMARY KEY (id));
insert into table_b values (1,'item1',false),(2,'item2',true),(3,'item2',null);
create view view_test as (
select a.*,b.item as b_item from table_a a left join table_b b on a.b_id=b.id and b.deleted=false
);

検証

table_a

id b_id item
1 1 item1
2 2 item2
3 3 item3
4 Null item4

table_b

id item deleted
1 item1 False
2 item2 True
3 item3 Null
select * from view_test

結果

id b_id item b_item
1 1 item1 item1
2 2 item2
3 3 item3
4 Null item4

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/21 20:38

    saziさん

    ありがとうございます。いただいたSQLでローカル確認してみましたが、期待通りになりますね…。
    私としても元のクエリの方が単純で良いと思っていますので、
    本質問はクローズにしてしまいましたが、もう少し調査してみます。

    結果はこちらに記載させていただきます。
    わざわざ追伸ありがとうございます。

    キャンセル

checkベストアンサー

0

この書き込みを読んでいる人が現象を再現できるだけの必要最小限の情報(テーブル定義やテーブル中に存在するデータ)を提示してください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/19 15:10

    Orlofskyさん

    再現情報としてはサブクエリを使わないとon句のキーが紐づかなかったためのようです。
    質問を編集して意図が理解できるようにしてクローズします。

    御回答ありがとうございました。

    キャンセル

  • 2018/05/19 16:32

    質問にはありませんが、ちょっと気になったので。
    where deleted = false のためだけにインランビューにしてますが、通常は deleted = false で必要なデータを大幅に絞り込める用途以外はインランビューにはしません。on の次に where を記述することが多いです。保守性を高めるためにSQLを無意味に複雑にしないことは大切です。
    https://qiita.com/Papageno/items/ab87e8a0cde8e514ab3f

    キャンセル

  • 2018/05/19 16:42

    Orlofskyさん

    whereの位置についてですが、今回のケースですと複数のサブクエリ下で将来的にそれなりの数(のdeleted=true)が出る予測があります。
    ご指摘を受けて改めて検討してみましたが、大幅に絞り込める用途としては合致しているのかなと考えました。

    よって一旦はこのままとしたく思っています。追伸のご指摘ありがとうございました。
    また何かの時に質問させていただくかもしれません。よろしくお願いいたします。

    キャンセル

0

結合元テーブルの結合キーがnullの場合には副問い合わせを行ってレコードを作らないといけないようです。
※この認識が正しいか、正確な知識が足りないため若干怪しいと思っているのですが…。

補足(解決)情報欄を質問箇所に追記いたしました。
皆様、ありがとうございました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

こちらについて追伸をしそびれていましたが、結局sazi様に記載していただいた通り、
元のSQLでも問題はなかったようです。

なぜかPCを再起動したりしたところ、元のSQLでも問題なく結果が出せるようになりました…。
大変お騒がせいたしました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.51%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • SQL

    2460questions

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

  • PostgreSQL

    1097questions

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