teratail header banner
teratail header banner
質問するログイン新規登録

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

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

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

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

Q&A

解決済

1回答

536閲覧

【PostgreSQL】前方一致するレコード以外のレコードを抽出するSQLクエリ

k0u_maeda

総合スコア3

PostgreSQL

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

0グッド

0クリップ

投稿2023/07/10 06:14

編集2023/07/10 07:27

0

0

実現したいこと

  • 以下のテーブル(前提に記載)において、idが同じname同士を比較し、末尾2文字以外の文字列が前方一致するレコード以外のレコードを抽出する。

前提

  • テーブル(以下、Table)
idname
integercharacter varying(文字数制限なし)
  • 利用環境
    PostgreSQL 15.3, compiled by Visual C++ build 1914, 64-bit (Windows)

例、期待結果、現状

  • idname
    1abcdefg0
    1abcdefg1
    1abcdefg
    1xyz
    2abcdefg
    2xyz
  • 期待結果

    idname
    1xyz
    2abcdefg
    2xyz

(注釈)id = 1において、name = 'abcdefg0', 'abcdefg1', 'abcdefg'の末尾2文字以外の文字列が前方一致するため、それら以外のレコードが抽出されることを期待する。

  • 現状
    すべてのレコードが抽出されない状況(出力結果0行)

該当のソースコード

PostgreSQL

1SELECT t1.id, t1.name 2FROM Table t1 3WHERE NOT EXISTS ( 4 SELECT * 5 FROM Table t2 6 WHERE t1.id = t2.id 7 AND t1.name LIKE CONCAT(substring(t2.name, 1, length(t2.name) - 2), '%') 8) 9ORDER BY id;

試したこと

  1. 末尾2文字以外の文字列を「substring(t2.name, 1, length(t2.name) - 2)」で表現。
  2. 前方一致するかの判断を「LIKE」演算子 + 「CONCAT」関数と「%」(ワイルドカード)で表現。
  3. 1, 2が一致しないものを抽出するため、「NOT EXISTS」を使用。

要旨

お恥ずかしい限りですが、「試したこと」に記載の内容へ辿り着くのに数日要しました。ここからどう変えれば良いか、何が間違っているのか分からず止まっています。
どんなことでも構いませんので、ご教示いただけたら幸いです。よろしくお願いいたします。

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

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

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

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

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

hoshi-takanori

2023/07/10 07:36

「末尾2文字以外の文字列が前方一致」という条件が微妙に曖昧というか、substring で末尾 2 文字を取り除いた結果は 'abcdef', 'abcdef', 'abcde' なので、'abcdefg' は残ってしまうような…。
guest

回答1

0

ベストアンサー

EXISTS句で利用しているサブクエリにT1.name <> T2.nameという条件が不足していそうです。

SQL

1SELECT * 2FROM T AS T1 3WHERE NOT EXISTS ( 4 SELECT * 5 FROM T AS T2 6 WHERE T1.id = T2.id 7 AND T1.name <> T2.name 8 AND T2.name LIKE CONCAT(SUBSTRING(T1.name, 1, LENGTH(T1.name)-2), '%') 9);

投稿2023/07/10 08:41

neko_the_shadow

総合スコア2395

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

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

k0u_maeda

2023/07/10 10:11

ご回答ありがとうございます。 ご指摘の通り、サブクエリ内の条件「T1.name <> T2.name」が抜けておりました。 この条件が無いと、無条件にすべてのレコードが抽出されない結果となってしまいますね。 サブクエリの理解が足りていなかったようです。。 初めて質問させていただきましたが、ご丁寧に回答いただきとてもありがたい限りです。 この度は誠にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.30%

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

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

質問する

関連した質問