C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

SQLServer:containsの問い合わせについて

[トピック内 20 記事 (1 - 20 表示)]  << 0 >>

■100711 / inTopicNo.1)  SQLServer:containsの問い合わせについて
  
□投稿者/ 虎一 (1回)-(2022/10/21(Fri) 13:31:02)

分類:[データベース全般] 

2022/10/24(Mon) 13:15:42 編集(投稿者)

SQLServer2019 を使用しています。

FREEKEYWORDというテーブルのSEARCHTEXTというカラム(ntext型)に "ABC-12345_01" という文字列を登録しています。

この項目に対して以下の問い合わせをしても返ってこないのですが、原因わかりますでしょうか。
select * from FREEKEYWORD where contains(SEARCHTEXT, '"*C-12345*"')

以下の問い合わせだと返ってきました。
select * from FREEKEYWORD where contains(SEARCHTEXT, '"*ABC-12345*"')
select * from FREEKEYWORD where contains(SEARCHTEXT, '"*-12345*"')

ちなみに、以下は返ってきませんでした。
select * from FREEKEYWORD where contains(SEARCHTEXT, '"*BC-12345*"')

お詳しい方がいらっしゃいましたらご教授いただければ幸いです。
宜しくお願い致します。
引用返信 編集キー/
■100712 / inTopicNo.2)  Re[1]: SQLServer:containsの問い合わせについて
□投稿者/ ぶなっぷ (295回)-(2022/10/21(Fri) 13:52:34)
2022/10/21(Fri) 13:55:07 編集(投稿者)
contains の 場合、*(ワイルドカード)は不要では?
ワイルドカード使いたい場合は、Like構文の %指定だと思います。

なお、containsで済む要件なら、Likeより高速な模様。
https://www.web-dev-qa-db-ja.com/ja/sql-server/sql-server%E3%81%A7%E3%81%AElike%E3%81%A8contains%E3%81%AE%E9%96%A2%E4%BF%82/940184310/

引用返信 編集キー/
■100713 / inTopicNo.3)  Re[2]: SQLServer:containsの問い合わせについて
□投稿者/ 虎一 (3回)-(2022/10/21(Fri) 14:11:17)
No100712 (ぶなっぷ さん) に返信
> 2022/10/21(Fri) 13:55:07 編集(投稿者)
>
> contains の 場合、*(ワイルドカード)は不要では?
> ワイルドカード使いたい場合は、Like構文の %指定だと思います。
>
> なお、containsで済む要件なら、Likeより高速な模様。
> https://www.web-dev-qa-db-ja.com/ja/sql-server/sql-server%E3%81%A7%E3%81%AElike%E3%81%A8contains%E3%81%AE%E9%96%A2%E4%BF%82/940184310/

早速のご返信ありがとうございます。

ここのサイトを見るとワイルドカードの指定は*と記載されていました。
https://www.ipentec.com/document/sql-fulltext-search

以下のLIKEでは結果が返ってくるのを確認しています。
select * from FREEKEYWORD where SEARCHTEXT LIKE '%C-12345%'

システム内で contains を使用しているので調査しているのですが分からなくて困っております。。。
引用返信 編集キー/
■100714 / inTopicNo.4)  Re[1]: SQLServer:containsの問い合わせについて
□投稿者/ furu (183回)-(2022/10/21(Fri) 14:53:14)
No100711 (虎一 さん) に返信
SQLServer使ったことはなく、今CONTAINSの仕様読んだだけなので
間違っているかもしれません。

*は単語の後に付けるようです。

> select * from FREEKEYWORD where contains(SEARCHTEXT, '"*C-12345*"')
Cという単語がないので不一致

> select * from FREEKEYWORD where contains(SEARCHTEXT, '"*BC-12345*"')
BCという単語がないので不一致
引用返信 編集キー/
■100715 / inTopicNo.5)  Re[2]: SQLServer:containsの問い合わせについて
□投稿者/ 虎一 (4回)-(2022/10/21(Fri) 15:28:25)
No100714 (furu さん) に返信
> ■No100711 (虎一 さん) に返信
> SQLServer使ったことはなく、今CONTAINSの仕様読んだだけなので
> 間違っているかもしれません。
>
> *は単語の後に付けるようです。
>
>>select * from FREEKEYWORD where contains(SEARCHTEXT, '"*C-12345*"')
> Cという単語がないので不一致
>
>>select * from FREEKEYWORD where contains(SEARCHTEXT, '"*BC-12345*"')
> BCという単語がないので不一致

ご返信ありがとうございます。

私もcontains の仕様を調べているのですが、どうも文字列を分割してトークンという塊にしてるような仕組み、でしょうか。
単語がないというのは、そのトークン内にないからという意味ですよね。

すみません、like と同じような扱いにするにはSQLをどう変更すればよいかって分かりますでしょうか。
引用返信 編集キー/
■100716 / inTopicNo.6)  Re[3]: SQLServer:containsの問い合わせについて
□投稿者/ ぶなっぷ (297回)-(2022/10/21(Fri) 15:34:36)
なるほど、私も調べてみました。

ワイルドカードも使えるようですね。

ただ、「フルテキスト検索」というものになるようで、
あいまい一致検索になってしまうようです。

正規表現的な完全一致ならLIKEだそうです。

引用返信 編集キー/
■100717 / inTopicNo.7)  Re[4]: SQLServer:containsの問い合わせについて
□投稿者/ 虎一 (5回)-(2022/10/21(Fri) 15:54:43)
No100716 (ぶなっぷ さん) に返信
> なるほど、私も調べてみました。
>
> ワイルドカードも使えるようですね。
>
> ただ、「フルテキスト検索」というものになるようで、
> あいまい一致検索になってしまうようです。
>
> 正規表現的な完全一致ならLIKEだそうです。

ありがとうございます。
likeを使用していない理由なのですが、恐らく検索速度優先の為かと思われます。
(likeだと確か全件フルスキャンになってしまうため)

contains の方で、like と同じような検索が出来ないか探しているのですが、そのやり方が見つからない状況です・・・
引用返信 編集キー/
■100719 / inTopicNo.8)  Re[1]: SQLServer:containsの問い合わせについて
□投稿者/ HattariB (41回)-(2022/10/21(Fri) 21:48:46)
ヲイラはSQLServerというのが良くわかってないんですけど、
問い合わせが返ってくる方に付いていて、返ってこない方に付いていない
"DQ001.DQ001_"という文字列は省略可能なのですか?

引用返信 編集キー/
■100727 / inTopicNo.9)  Re[1]: SQLServer:containsの問い合わせについて
□投稿者/ アデル (2回)-(2022/10/22(Sat) 11:15:49)
全文検索のインデックスは文字列が単語単位で分割されて作られてるとするなら単語を途中で切ったものが検索できないことに理屈が通りますけどワイルドカードが何を表すかですね、任意の単語なのかな
引用返信 編集キー/
■100728 / inTopicNo.10)  Re[1]: SQLServer:containsの問い合わせについて
□投稿者/ KOZ (329回)-(2022/10/22(Sat) 13:07:33)
2022/10/22(Sat) 13:36:29 編集(投稿者)

No100711 (虎一 さん) に返信
> この項目に対して以下の問い合わせをしても返ってこないのですが、原因わかりますでしょうか。
> select * from FREEKEYWORD where contains(SEARCHTEXT, '"*C-12345*"')

詳しくないですが、ハイフンやアンダースコアがワードブレイカーとして働いてないですか?

「検索用のワード ブレーカー ステマーの&管理を構成する & (SQL Server)」
https://learn.microsoft.com/ja-jp/sql/relational-databases/search/configure-and-manage-word-breakers-and-stemmers-for-search?view=sql-server-ver16

「登録済みのフィルターおよびワード ブレーカーの表示または変更」
https://learn.microsoft.com/ja-jp/sql/relational-databases/search/view-or-change-registered-filters-and-word-breakers?view=sql-server-ver16

確認してみては?

引用返信 編集キー/
■100729 / inTopicNo.11)  Re[2]: SQLServer:containsの問い合わせについて
□投稿者/ KOZ (330回)-(2022/10/22(Sat) 13:24:03)
No100728 (KOZ) に返信

「フルテキスト インデックスについてのメモ (2015/5/17)」
https://blog.engineer-memo.com/2015/05/17/%E3%83%95%E3%83%AB%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88-%E3%82%A4%E3%83%B3%E3%83%87%E3%83%83%E3%82%AF%E3%82%B9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E3%81%AE%E3%83%A1%E3%83%A2-2015517/

によると、

DECLARE @SearchQuery nvarchar(max) = N'<検索文字列>'
SELECT * FROM sys.dm_fts_parser( @SearchQuery, 1041, 0, 0)

で、文字列がどのようにワードブレークされるかを確認することができるようです。

引用返信 編集キー/
■100735 / inTopicNo.12)  Re[3]: SQLServer:containsの問い合わせについて
□投稿者/ 伝説のカレー (46回)-(2022/10/22(Sat) 18:54:05)
No100729 (KOZ さん) に返信
良いですねこれ、形態素解析による全文検索は検索漏れが宿命なんですよね

N-gramによる全文検索だと検索漏れがないけれども関連性が低いものまでヒットしてしまう検索ノイズが多くなるというトレードオフがあります
SQLServerで使えるのは形態素解析のみのようですね

・SQLServerで辞書登録を頑張る
・SQLServerでクエリを投げる前に前処理で単語を良い感じに補完する
・Elasticsearchのような全文検索エンジンでN-gramを使う

SQLServerとは別に全文検索を行う場合インデックスを作成する処理を定期的に行わないといけなくなります
どれも簡単ではなさそうですよね

ユーザが検索したそうな値を別カラムに予め抽出しておいてそっちにインデックス張るとか、うーんどうでしょうね
引用返信 編集キー/
■100746 / inTopicNo.13)  Re[2]: SQLServer:containsの問い合わせについて
□投稿者/ 虎一 (6回)-(2022/10/24(Mon) 11:36:53)
2022/10/24(Mon) 13:16:22 編集(投稿者)

No100719 (HattariB さん) に返信
> ヲイラはSQLServerというのが良くわかってないんですけど、
> 問い合わせが返ってくる方に付いていて、返ってこない方に付いていない
> "DQ001.DQ001_"という文字列は省略可能なのですか?
>

すいません、遅くなりました。
"DQ001.DQ001_" こちら、実際に使用しているSQLをそのまま貼り付けておりました。
上部のSQLにも付いているのですが、長くなって見辛いので削除しておりました。修正させてもらいました。
混乱させてしまって申し訳ありません。
引用返信 編集キー/
■100747 / inTopicNo.14)  Re[4]: SQLServer:containsの問い合わせについて
□投稿者/ 虎一 (7回)-(2022/10/24(Mon) 11:39:07)
アデル様
KOZ様
伝説のカレー様

ご返信ありがとうございます。
内容確認させていただき、またご報告させていただきます。
お忙しいところお力添えいただきありがとうございます。
引用返信 編集キー/
■100748 / inTopicNo.15)  Re[3]: SQLServer:containsの問い合わせについて
□投稿者/ 虎一 (8回)-(2022/10/24(Mon) 13:23:44)
2022/10/24(Mon) 13:41:35 編集(投稿者)

No100729 (KOZ さん) に返信
> DECLARE @SearchQuery nvarchar(max) = N'<検索文字列>'
> SELECT * FROM sys.dm_fts_parser( @SearchQuery, 1041, 0, 0)
>
> で、文字列がどのようにワードブレークされるかを確認することができるようです。

すみません、上記SQLをA5M2で実行したらエラーになりました。

で、ちょっと改修して・・・
SELECT * FROM sys.dm_fts_parser (' "ABC-12345" ', 1041, 0, 0)
として流したところ、display_term列に以下のように返ってきました。
--------------------------------
abc-12345
abc
12345
nn12345
--------------------------------
c や bc がないから、
select * from FREEKEYWORD where contains(SEARCHTEXT, '"*C-12345*"')
select * from FREEKEYWORD where contains(SEARCHTEXT, '"*BC-12345*"')
では「返ってこない」ということでしょうか。
引用返信 編集キー/
■100750 / inTopicNo.16)  Re[4]: SQLServer:containsの問い合わせについて
□投稿者/ トット (1回)-(2022/10/24(Mon) 15:09:47)
https://learn.microsoft.com/en-us/sql/t-sql/queries/contains-transact-sql?view=sql-server-ver16

先頭にアスタリスクを付けるのは構文として無効な気がします

<prefix_term>に定義されてるようにアスタリスクは文字列の末尾につけたときに共通プリフィクスの文字列を検索できますよというものです

C-12345も同じようにsys.dm_fts_parseで調べればいんじゃないですかね
違う単語になったら検索できないです
引用返信 編集キー/
■100752 / inTopicNo.17)  Re[5]: SQLServer:containsの問い合わせについて
□投稿者/ kiku (300回)-(2022/10/24(Mon) 16:36:52)
No100750 (トット さん) に返信
> https://learn.microsoft.com/en-us/sql/t-sql/queries/contains-transact-sql?view=sql-server-ver16
> 先頭にアスタリスクを付けるのは構文として無効な気がします
> <prefix_term>に定義されてるようにアスタリスクは文字列の末尾につけたときに共通プリフィクスの文字列を検索できますよというものです
> C-12345も同じようにsys.dm_fts_parseで調べればいんじゃないですかね
> 違う単語になったら検索できないです

SELECT * FROM sys.dm_fts_parser ('"ABC-12345"', 1041, 0, 0)

special_term display_term
Exact Match abc-12345
Exact Match abc
Exact Match 12345
Exact Match nn12345

SELECT * FROM sys.dm_fts_parser ('"C-12345"', 1041, 0, 0)

special_term display_term
Exact Match c-12345
Noise Word c
Exact Match 12345
Exact Match nn12345

Noise Wordとなっているところが気になりますね。


引用返信 編集キー/
■100754 / inTopicNo.18)  Re[5]: SQLServer:containsの問い合わせについて
□投稿者/ KOZ (332回)-(2022/10/24(Mon) 16:50:32)
No100750 (トット さん) に返信
> https://learn.microsoft.com/en-us/sql/t-sql/queries/contains-transact-sql?view=sql-server-ver16
> 先頭にアスタリスクを付けるのは構文として無効な気がします
> <prefix_term>に定義されてるようにアスタリスクは文字列の末尾につけたときに共通プリフィクスの文字列を検索できますよというものです

私もそう思います。
前方一致だとフルスキャンするしかないので、無視されてるんじゃないでしょうか。

引用返信 編集キー/
■100755 / inTopicNo.19)  Re[6]: SQLServer:containsの問い合わせについて
□投稿者/ 伝説のカレー (49回)-(2022/10/24(Mon) 19:43:58)
No100752 (kiku さん) に返信
> SELECT * FROM sys.dm_fts_parser ('"C-12345"', 1041, 0, 0)
>
> special_term display_term
> Exact Match c-12345
> Noise Word c
> Exact Match 12345
> Exact Match nn12345
>
> Noise Wordとなっているところが気になりますね。

ノイズワードはインデックスが作成されない文字列を表すんでしょうねきっと

ABC-12345がデータとして存在しているなら
・abc
・12345
のインデックスが作成されている

C-12345はCがノイズとして除去されて
・12345
が単語として抽出される

そうすると"C-12345"で検索したときに"ABC-12345"が取得できそうなものですけどね
それができないということは""で囲ったときはノイズも含めて一致するものがないとマッチしないってことなんでしょうねー
引用返信 編集キー/
■100758 / inTopicNo.20)  Re[6]: SQLServer:containsの問い合わせについて
 
□投稿者/ 虎一 (9回)-(2022/10/24(Mon) 20:54:28)
トット様
kiku様
KOZ様
伝説のカレー様

いただいた情報を元に現在ではちょっと対応が難しいということを報告しようかと思います。
contains、なかなか難しいですね。。。
ありがとうございました。
解決済みにしておきますが、調査は時間を見つけて進めてみようかと思っています。

解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ