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

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

新規登録して質問してみよう
ただいま回答率
85.48%
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

解決済

2回答

795閲覧

SQLで条件分岐の結果によって異なる条件で検索したい

ttttttt

総合スコア3

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クリップ

投稿2022/10/09 07:42

編集2022/10/11 09:35

SQLで条件分岐の結果によって異なる条件で検索したいです。※条件は以降に記載
DBはPostgreSQLです。
CASE文など試行錯誤してみたのですがうまくいかず、そもそもこのようなことができるのかすら不明な状態で困り果てています。ご教授のほどよろしくお願いいたします。

やりたいこと(条件)

入力値に応じて、テーブルMを検索した結果が

  1. 1件以上ある場合、テーブルTから入力値に応じたレコードを取得
  2. 0件の場合、テーブルTから入力値+日付(t_date)が最も新しいレコードを取得
具体例
  1. id「01」t_char「a」を指定した場合、テーブルTから①②を取得
  2. id「03」t_char「a」を指定した場合、テーブルTから④を取得

↓テーブル構造など

sql

1--テーブルM 2CREATE TABLE M 3( 4 id VARCHAR(10), 5 t_char VARCHAR(10), 6 PRIMARY KEY (id,t_char) 7); 8INSERT INTO M (id,t_char) VALUES ('01','a'); 9--テーブルT 10CREATE TABLE T 11( 12 id VARCHAR(10), 13 t_char VARCHAR(10), 14 t_2 VARCHAR(10), 15 t_date date, 16 PRIMARY KEY (id,t_char,t_2) 17); 18INSERT INTO T (id,t_char,t_2,t_date) VALUES ('01','a','あ','2022/10/09');--① 19INSERT INTO T (id,t_char,t_2,t_date) VALUES ('01','a','い','2022/10/10');--② 20INSERT INTO T (id,t_char,t_2,t_date) VALUES ('03','a','あ','2022/10/09');--③ 21INSERT INTO T (id,t_char,t_2,t_date) VALUES ('03','a','い','2022/10/10');--④

追記

idやt_charは外部(アプリ側)から入力される想定です。

追記2

ダメもとで下記のようなものを試しましたが、ダメでした。

SELECT
COUNT(*) as c
CASE
WHEN c>1 THEN (SELECT * FROM T WHERE id = '01' AND t_char = 'a')
ELSE 0--todo条件②の条件を指定する
END
FROM M
WHERE
id = '01'
AND
t_char = 'a'

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

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

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

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

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

m.ts10806

2022/10/09 08:02

ご自身で試されたことを記載願います。
hatena19

2022/10/09 13:40

> 2. 0件の場合、テーブルTから入力値+日付(t_date)が最も新しいレコードを取得 > 2. id「03」t_char「a」を指定した場合、テーブルTから④を取得 というのがよくわかりません。 id「03」t_char「a」のレコードは③④の2件ありますので、③④の表示ではないのですか。 また、「入力値+日付(t_date)が最も新しいレコード」というのもあいまいな表現です。 正確な表現にできませんか。
KOZ6.0

2022/10/10 03:03

id「03」t_char「b」を指定した場合(T の中に存在しない場合)はどうなるのですか? ゼロ件ですか?、入力値+日付(t_date)が最も新しいレコードになるのですか?
ttttttt

2022/10/11 09:07

ご確認いただきありがとうございました! 返信が遅くなり申し訳ございません。 @m.ts10806さま ダメもとで下記のようなものを試しましたが、ダメでした。 SELECT COUNT(*) as c CASE WHEN c>1 THEN (SELECT * FROM T WHERE id = '01' AND t_char = 'a') ELSE 0--todo条件②の条件を指定する END FROM M WHERE id = '01' AND t_char = 'a' @hatena19さま >id「03」t_char「a」のレコードは③④の2件ありますので、③④の表示ではないのですか。 id「03」かつt_char「a」のレコードのなかから、t_dateの日付が最も新しいレコードという意味です。③のt_date「2022/10/09」よりも④のt_date「2022/10/10」のほうが新しいため、④が取得されてほしいです。 @KOZ6.0さま >id「03」t_char「b」を指定した場合(T の中に存在しない場合)はどうなるのですか? 0件の想定です。
KOZ6.0

2022/10/11 09:15

> id「03」かつt_char「a」のレコードのなかから、t_dateの日付が最も新しいレコードという意味です。 具体例1と矛盾してるような気がします。具体例1と2の違いは何ですか?
ttttttt

2022/10/11 09:23

@KOZ6.0さま 具体例1:id「01」t_char「a」を指定した場合、テーブルTから①②を取得 はMの検索結果が1件以上の場合に表示したい内容、具体例2:id「03」t_char「a」を指定した場合、テーブルTから④を取得 はMの検索結果が0件の場合に表示したい内容を指します。矛盾していますでしょうか?
m.ts10806

2022/10/11 09:30

>ダメもとで下記のようなものを試しましたが、ダメでした。 質問本文に追記を。
KOZ6.0

2022/10/11 09:53

追記を見て要件が理解できた気がしますが、外部(アプリ側)とは何ですか? それによって回答が変わってくるはずです。
m.ts10806

2022/10/11 09:57

確かにSQLだけで何とかするよりアプリ側でSQLを動的に組み立てた方がスッキリできそうにおもいます。 条件増えたときにかなりややこしくなります。
ttttttt

2022/10/11 12:01

@質問者さま アドバイスいただきありがとうございます! SQLだけでやる方法はないものか考えていたのですが、厳しそうなことがわかりました。 いったんほかの方法を検討しようと思います。 @KOZ6.0さま >外部(アプリ側)とは何ですか? 説明が難しいのですが、いわゆるプログラミング言語ではなく、ツールを通じて引数を渡すイメージです。(答えになってないですね。すいません。。。) ストアドファンクションについては恥ずかしながら初めて認識しましたので、ツール上で利用できるか確認しようと思います。
KOZ6.0

2022/10/11 23:43

そのツールで与えた入力値は SQL 上、どのように表現するのでしょうか? たとえば、バインド変数だと、@id, :t_char, あるいは ? などで表現しますよね?
ttttttt

2022/10/12 00:30

@KOZ6.0さま /*id*/ のように引き渡します。2WaySQLというそうです。
guest

回答2

0

ベストアンサー

SQL 一発で検索する方法です。
M の検索結果によって実行される検索パターン2つを hatena19 さんの回答に倣い、UNION ALL でくっつけています。
ストアドファンクションの実装は、ご自身で研究してみてください。

SQL

1SELECT T.* FROM T WHERE T.id = /*id*/ AND T.t_char = /*t_char*/ 2AND EXISTS(SELECT 1 FROM M WHERE M.id = /*id*/ AND M.t_char = /*t_char*/) 3UNION ALL 4SELECT * FROM (SELECT T.* FROM T WHERE T.id = /*id*/ AND T.t_char = /*t_char*/ ORDER BY T.t_date DESC LIMIT 1) T1 5WHERE NOT EXISTS(SELECT 1 FROM M WHERE M.id = /*id*/ AND M.t_char = /*t_char*/)

投稿2022/10/12 00:57

KOZ6.0

総合スコア2626

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

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

ttttttt

2022/10/12 09:20

アドバイスいただきありがとうございました!つたない質問内容か要件を聞き出してくださったKOZ6.0さまをbベストアンサーとして選ばせていただきます。 ストアドファンクションについては、今回の実行環境では利用できなさそうでしたが、今後の参考とさせていただきます。
guest

0

質問の条件にあいまいな部分があるので、下記のような条件だと仮定して回答します。

条件

  1. Mの id, t_char と一致する T のレコードを抽出
  2. 上記の結果が0件の場合、id, t_date の降順で並べたときの先頭のレコードを出力

SQL

1SELECT T.* FROM T INNER JOIN M ON T.id = M.id AND T.t_char = M.t_char 2UNION ALL 3SELECT * FROM (SELECT T.* FROM T ORDER BY id DESC, t_date DESC LIMIT 1) T1 4WHERE NOT EXISTS(SELECT 1 FROM T INNER JOIN M ON T.id = M.id AND T.t_char = M.t_char);

追記

idやt_charは外部(アプリ側)から入力される想定です。

id「03」かつt_char「a」のレコードのなかから、t_dateの日付が最も新しいレコードという意味です。③のt_date「2022/10/09」よりも④のt_date「2022/10/10」のほうが新しいため、④が取得されてほしいです。

下記のようなことかな?

SQL

1SELECT * FROM T 2WHERE 3id = '01' AND t_char = 'a' 4AND EXISTS(SELECT 1 FROM M WHERE id = '01' AND t_char = 'a') 5UNION ALL 6SELECT * FROM 7 (SELECT T.* FROM T 8 WHERE 9 id = '01' AND t_char = 'a' 10 AND NOT EXISTS(SELECT 1 FROM M WHERE id = '01' AND t_char = 'a') 11 ORDER BY t_date DESC LIMIT 1) T1;

投稿2022/10/09 15:42

編集2022/10/11 13:41
hatena19

総合スコア33715

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

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

ttttttt

2022/10/12 09:21

追記ありがとうございます! 上記でも取得したい結果が得られそうでした。感謝いたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問