SQLiteメモ:複数カラムにマッチするパターンをSELECTする方法

自前高速検索を修正しました検索できない場合があったからですが、キーワードを複数カラムのどれかにマッチするという条件の式に問題があったためです。

今までは下記の様な感じでSELECTを行っていました。(判りやすくする為に簡略化しています。)

「E.entry_text||E.entry_text_more||E.entry_title LIKE ‘%530購入%’」はMTの記事の本文、タイトル、追記にキーワード「530購入」が存在するかチェックするLIKE文です。
「E.entry_text LIKE ‘%530購入%’ OR E.entry_text_more  LIKE ‘%530購入%’ OR E.entry_title LIKE ‘%530購入%’」とする判りにあらかじめ本文、タイトル、追記の文字列を連結してLIKEを行う方法です。

下記の場合何故かマッチしないので色々試してみるとentry_text_moreの部分を取り除いて見ると上手くいく。何でかな-と思って色々検索してみると、

複数カラムに対するLIKE文の最適化 – 教えて!goo
<http://oshiete1.goo.ne.jp/qa1599858.html>

がヒットした。読んでみると下記のSQLの場合複数カラムのうち一つでもNULLのカラムがあると全部NULLになってしまい、マッチしなくなるらしい。となるとentry_text_moreを取り除くと上手くマッチするのも納得できる。追記は書かれているエントリーとかかれていないエントリーがあるので追記がない記事は検索できないことになる。ヽ(´ー`)ノダメジャン

そして上記の記事を参考にするとconcat関数を使えば良いらしい。実際に試してみるとSQLite対応していない模様、何か変わりになる関数は無いものかと色々探してみたものの無い感じ。何時も参考にさせていただいている下記のサイトの「coalesce」って言う関数が使えそうなんだけど、

「coalesce(X,Y,…)…引数のうち NULL でない最初のもののコピーを返します。引数のいずれも NULL の場合は NULL が返されます。少なくとも2個の引数が必要です。」

そうじゃなくてNULLの時に別の文字を返すか変換するような関数がほしいんだけどーーー。と思って激しくスルー(<大バカ)

SQLite が認識できるクエリー言語
<http://www.net-newbie.com/sqlite/lang.html>

SELECT
    E.entry_id
FROM 
    mt_entry AS E
WHERE
    E.entry_text||E.entry_text_more||E.entry_title LIKE ‘%530購入%’

そのうち色々検索していると下記のページを発見、それらしい関数が色々あるので片っ端から検索してみる
Firebird Reference Manual
<http://cvs.sourceforge.jp/cgi-bin/viewcvs.cgi/firebird-jp-doc/reference/firebird_reference.html?rev=1.4>

すると「IFNULL」という関数が何だか使えそうでSQLiteもつかえるっぽい。検索してみるとまた

SQLite が認識できるクエリー言語
<http://www.net-newbie.com/sqlite/lang.html>

のサイトが検索に引っ掛かったので見てみると

「ifnull(X,Y)…引数のうち NULL でない最初のもののコピーを返します。引数のいずれも NULL の場合は NULL が返されます。前述の coalesce() と同じ振る舞いをします。」

coalesceと同じ振る舞いってだめじゃん(‘Д`)ナムーとか思っていると、ひらめいた( ゚∀゚)ピキーン!

よく考えてみると、「NULLではない最初のもののコピーを返します。」ということは、「ifnull(E.entry_text_more,”)」とすればentry_text_moreがNULLの時は次の「”」(から文字)が返るんじゃね?俺って天才じゃね?(<大バカ)

で、改良したのが下、上手くいきました。

SELECT
    E.entry_id 
FROM
    mt_entry AS E 
WHERE 
    ifnull(E.entry_text,”)||ifnull(E.entry_text_more,”)||ifnull(E.entry_title,”) LIKE ‘%530購入%’ ORDER BY E.entry_id LIMIT 100

つまり、ifnullかcoalesceを使えばよかったわけです。

entry_text_moreにだけifnullすればいいんだけど、念のため全部にifnullしてます。

回りまわって実は最初に見つけたcoalesceでよかったわけです。つ´Д`)つ

タグ : , ,