以下のクエリ例では、MySQLを使用して指定された結果セットを取得しますが、実際には「あいまい一致」を実行しません。少なくとも、アルゴリズムを説明する方法ではありません。(これにより、説明したアルゴリズムが実装されます。値で並べ替えてから、各値をチェックして、先頭部分が以前に取得した値と「一致」するかどうかを確認します。)
これにより、以前に取得した行の値に対する近傍値の先頭部分の「完全一致」が検出されます。一致についての「あいまいさ」は実際にはありません。
クエリが「不一致」の値を検出すると、その値が「不一致」であることを示します。次に取得される値について、その値が以前の「一致しない」値で始まるかどうかをチェックします。文字列の先頭部分が完全に一致する場合、値は破棄されます。それ以外の場合、値は「一致しない」値としてマークされ、保持されます。
このアプローチでは、インラインビュー(またはMySQLが参照する「派生テーブル」)を使用します。最も内側のインラインビュー(別名s)は、近隣の個別の値のソートされたリストを取得します。「トリック」(それを呼び出したい場合)は、次のインラインビュー(「t」とも呼ばれます)にあり、MySQLユーザー変数を使用して以前に取得した値を参照します。
「特殊文字」の問題を回避するために、先頭の文字の等式比較を行います。
クエリ全体は次のとおりです。
SELECT t.neighborhood
FROM (
SELECT IF(IFNULL(LEFT(s.neighborhood,CHAR_LENGTH(@match)) <> @match,1),@match := s.neighborhood,NULL) AS neighborhood
FROM (SELECT RTRIM(neighborhood) AS neighborhood
FROM mytable
JOIN (SELECT @match := NULL) r
GROUP BY neighborhood
ORDER BY neighborhood
) s
) t
WHERE t.neighborhood IS NOT NULL
@match変数の初期化と、現在の値と前の値の比較を実行する式を除いて、すべて非常に簡単です。
値の特殊文字によって導入されるコーナーケースに関心がない場合は、より単純なLIKEまたはREGEXPを使用して比較を行うことができます。
s.neighborhood NOT LIKE CONCAT(@match,'%')
s.neighborhood NOT REGEXP CONCAT('^',@match)
LIKE演算子にはアンダースコアとパーセント文字が使用され、REGEXPには正規表現で使用される特殊文字が使用されます。これらの問題を回避するために、上記のクエリでは、見た目が少し扱いにくい比較を使用しています。
LEFT(s.neighborhood,CHAR_LENGTH(@match)) <> @match
これは、前の値(@match:='Park View'など)を取得し、それを次の値の先頭部分(' Park View'の長さまで)と比較して、一致するかどうかを判断します。
このクエリを使用したアプローチの利点の1つは、返される値が後続のクエリの述語で「一致」することが保証されることです。このクエリを使用して近隣のリストを取得していて、ユーザーがそのリストを選択したとします。これにより、すべての行に「一致」する値のセットが返されます。
後続のクエリでは、単純な述語(WHERE句)の任意の戻り値を使用して、一致する行を返すことができます。たとえば、ユーザーが値「五大湖」を選択した場合:
SELECT t.*
FROM mytable t
WHERE LEFT(t.neighborhood,CHAR_LENGTH('Great Lake') = 'Great Lake'
一致するためにLIKEまたはREGEXP述語を使用した場合、後続のクエリの述語で対応する一致を使用する必要があります。
SELECT t.*
FROM mytable t
WHERE t.neighborhood LIKE CONCAT('Great Lake','%')
SELECT t.*
FROM mytable t
WHERE t.neighborhood REGEXP CONCAT('^','Great Lake')