

## 実行したいこと

検索条件にはテーブルteiki．teiki_oyaprod_cdのteikioya1を使って理想実行結果のようなデータを取得したいです。  
追記:  
teiki.teiki_oyaprod_cdに加えてteikimeisai.teikiprod_cd(wa,wbs,wc)も検索時の条件に加えられるようになりました。自分なりにも解決できるかも知れませんがアドバイス等頂けたら幸いです。

  * 理想実行結果のmeisaiにはteikimeisai.meisai_noでセット子情報の場合はNULL
  * prod_cdには定期明細のteikiprod_cdもしくはteikiprod_cdの値がテーブルsetのset_oyaprod_cdに存在していればsetdetailのセット子情報set_prod_cdの値も取得してくる。セット子情報の並び順はsetdetailのseq昇順。
  * prod_nmにはテーブルprod.prod_nameの値
  * prod_priceにはテーブルprod.prod_priceの値でセット子情報のレコードの場合NULL
  * ソート順はteikimeisai.meisai_no,setdetail.seq

## 詰まった点

セット親の商品コードとセット子の商品コードを別レコードの同じカラムprod_cdで取得する方法が分からず詰まってしまいました。

まだSQL経験も浅く、質問も初なので不明瞭な点、申し訳ありません。分かる方、ご教授頂きたいです。  
PostgreSQLを利用しています。

### テーブル名:prod

prod_cd | prod_name | prod_price  
---|---|---  
wa | 定期1子A  | 1000  
wbs | 定期1子Bセット親 | 2000  
wb1 | セット子B1  | 1000  
wb2 | セット子B2  | 1000  
wc | 定期1子C  | 1000  
wds | 定期2子Dセット親  | 1000  
wd1 | セット子D1  | 1000  
teikioya1 | 定期親1  | 3000  
teikioya2 | 定期親2  | 3000  
  
### テーブル名:teiki

teiki_cd | teiki_oyaprod_cd  
---|---  
teiki1 | teikioya1  
teiki2 | teikioya2  
  
### テーブル名:teikimeisai

teiki_cd | meisai_no | teikiprod_cd  
---|---|---  
teiki1 | 1 | wa  
teiki1 | 2 | wbs  
teiki1 | 3 | wc  
teiki2 | 1 | wds  
  
### テーブル名:setprod

set_oyaprod_cd  
---  
wbs  
wds  
  
### テーブル名:setdetail

set_oyaprod_cd | seq | set_prod_cd  
---|---|---  
wbs | 1 | wb1  
wbs | 2 | wb2  
wds | 1 | wd1  
  
## 理想実行結果A

meisai | prod_cd | prod_nm | prod_price  
---|---|---|---  
1 | wa | 定期1子A1000 |  
2 | wbs | 定期1子Bセット親 | 2000  
| wb1 | セット子B1 |  
| wb2 | セット子B2 |  
3 | wc | 定期1子C | 1000  
  
## 理想実行結果B (Aの代わりにこちらでも構わない)

meisai | prod_cd | set_prod_cd | prod_nm | prod_price  
---|---|---|---|---  
1 | wa |  | 定期1子A | 1000  
2 | wbs |  | 定期1子Bセット親 | 2000  
|  | wb1 | セット子B1 |  
|  | wb2 | セット子B2 |  
3 | wc |  | 定期1子C | 1000  
  
* * *

# 追記：

以下はかなり理想実行結果Aに近くなりましたが、teikimeisai．teikiprod_cdの重複データがあるなど不完全で、これ以上の改善策が分からない状態です。

## 現状コード

[code]

    select tm.meisai_no meisai,
    
           p.prod_cd,
    
           p.prod_name prod_nm,
    
           case when ssd.set_oyaprod_cd is null
    
                then p.prod_price
    
                else null
    
           end prod_price
    
    from   prod        p
    
           left join teikimeisai tm
    
           on p.prod_cd = tm.teikiprod_cd
    
           left join setdetail sd
    
           on p.prod_cd = sd.set_prod_cd
    
           left join (select tm2.meisai_no,
    
                             tm2.set_oyaprod_cd,
    
                             sd2.set_prod_cd
    
                      from   teiki tk
    
                             join teikimeisai tm2
    
                             on tk.teiki_cd = tm2.teiki_cd
    
                             left join setprod sp
    
                             on tm2.teiki_prod_cd = sp.set_oyaprod_cd
    
                             left join setdetail sd2
    
                             on sp.set_oyaprod_cd = sd2.set_oyaprod_cd
    
                             where tk.teiki_cd = 'teikioya1') as ssd
    
           on p.prod_cd = ssd.sed_prod_cd
    
           on p.prod_cd = ssd.prod_cd
    
    order by coalesce(tm.meisai_no, ssd.meisai_no),
    
             ssd.seq nulls first
    
[/code]


CC BY-SA 4.0
2022-10-03T02:22:27.420
91410
2023-10-03T17:05:35.730
2022-10-04T06:19:12.017
54667
54667
question
sql postgresql
同じカラムに二種類のデータを取得する方法


`prod.prod_cd`が`teikimeisai.teikiprod_cd`に存在するレコードを「セット親」と推測します。  
セット親とセット子は別テーブルを参照するため左外部結合を使うのが通常の解法です。  
さらにセット子は複数のテーブルを結合するため、`join`文の中で副問い合わせを併用することになります。

下記のサンプルコードを参考にしてみてください。

**サンプルコード**

**Schema (PostgreSQL v14)**

[code]

    CREATE TABLE prod (
      "prod_cd" VARCHAR(100),
      "prod_name" VARCHAR(100),
      "prod_price" INTEGER
    );
    
    INSERT INTO prod
      ("prod_cd", "prod_name", "prod_price")
    VALUES
      ('wa', '商品A', '1000'),
      ('wbs', '商品Bセット', '2000'),
      ('wb1', '商品B1', '1000'),
      ('wb2', '商品B2', '1000'),
      ('wc', '商品C', '1000');
    
    CREATE TABLE teiki (
      "teiki_cd" VARCHAR(100),
      "teiki_oyaprod_cd" VARCHAR(100)
    );
    
    INSERT INTO teiki
      ("teiki_cd", "teiki_oyaprod_cd")
    VALUES
      ('teikia', 'teikioya');
    
    CREATE TABLE teikimeisai (
      "teiki_cd" VARCHAR(100),
      "meisai_no" INTEGER,
      "teikiprod_cd" VARCHAR(100)
    );
    
    INSERT INTO teikimeisai
      ("teiki_cd", "meisai_no", "teikiprod_cd")
    VALUES
      ('teikia', '1', 'wa'),
      ('teikia', '2', 'wbs'),
      ('teikia', '3', 'wc');
    
    CREATE TABLE "set" (
      "set_oyaprod_cd" VARCHAR(100)
    );
    
    INSERT INTO set
      ("set_oyaprod_cd")
    VALUES
      ('wbs');
    
    CREATE TABLE setdetail (
      "set_oyaprod_cd" VARCHAR(100),
      "seq" INTEGER,
      "sed_prod_cd" VARCHAR(100)
    );
    
    INSERT INTO setdetail
      ("set_oyaprod_cd", "seq", "sed_prod_cd")
    VALUES
      ('wbs', '1', 'wb1'),
      ('wbs', '2', 'wb2');
    
[/code]

* * *

**Query #1**

[code]

    select tm.meisai_no meisai,
           p.prod_cd,
           p.prod_name prod_nm,
           case when ssd.set_oyaprod_cd is null
                then p.prod_price
                else null
           end prod_price
    from   prod        p
           left join teikimeisai tm
           on p.prod_cd = tm.teikiprod_cd
           left join (select tm2.meisai_no,
                             s.set_oyaprod_cd,
                             sd.seq,
                             sd.sed_prod_cd
                      from   "set" s
                             join teikimeisai tm2
                             on s.set_oyaprod_cd = tm2.teikiprod_cd
                             join setdetail sd
                             on s.set_oyaprod_cd = sd.set_oyaprod_cd) as ssd
           on p.prod_cd = ssd.sed_prod_cd
    order by coalesce(tm.meisai_no, ssd.meisai_no),
             ssd.seq nulls first;
    
[/code]

meisai | prod_cd | prod_nm | prod_price  
---|---|---|---  
1 | wa | 商品A | 1000  
2 | wbs | 商品Bセット | 2000  
| wb1 | 商品B1 |  
| wb2 | 商品B2 |  
3 | wc | 商品C | 1000  
  
* * *

[View on DB Fiddle](https://www.db-fiddle.com/f/h1zs9rZ6HV7VNaWAZLcJnS/0)

**注記**

テーブル`teiki`の`teiki_oyaprod_cd`の必要性が読み取れなかったので使っていません。  
`prod`テーブル`wc`レコードの`prod_price`が1000ですので、理想実行結果の1500とは異なります。  
本テーブルは別名と思いますが、`set`のようにSQL文の構文そのものの単語は使わない方が可読性や保守性が上がります。

さて、スタックオーバーフローへようこそ！  
仕様を詳細に書いていただくことは必要かつありがたいのですが、どちらかというと詰まった点や試行錯誤した痕跡に重点をおいて記載していただくと適切な回答がつきやすくなります。  
※仕様と希望する動作のみ書かれた質問は、俗に「丸投げ」といわれる印象を与えてしまいます。

動かないSQL文であっても、SQLのコメントに `-- ここが分からない`
などの注釈付きで載せた方が回答者の解説が実態に即したものになりますので、この回答が不適切な場合や今後の質問で意識していただければ幸いです。


CC BY-SA 4.0
2022-10-03T05:33:27.983
91415
2022-10-03T05:33:27.983
9820
91410
answer