次のような別のテーブルを採用できます
ID KeywordID Word
1 1 blue
2 2 blue
3 1 cat
文字列を変換します
"Blue cat green eyes 2342342"
一連のインデックスとカウント:
SELECT KeywordID, COUNT(*) FROM ancillary WHERE Word IN ('blue','cat','green','eyes'...)
これは、一連の完全一致を実行して、たとえば、次のように返します。
KeywordID Count
1 2
2 1
次に、ID 1 のキーワード グループには 2 つの単語があることがわかります。つまり、カウント 2 はそれらすべてに一致することを意味します。したがって、keywordid 1 は満たされます。グループ 2 にも 2 つの単語 (black、cat) がありますが、見つかったのは 1 つだけで、一致はありますが完全ではありません。
キーワード ID と一緒にキーワード セットのサイズも記録すると、同じ ID のすべてのキーワードが同じ KeywordSize になり、GROUP BY もできます。
KeywordID KeywordSize Count
1 2 2
2 2 1
SELECT COUNT(*)/KeywordSize AS match ... ORDER BY match
また、キーワードの一致を関連性でソートすることもできます。
もちろん、KeywordID を取得すると、キーワード テーブルで見つけることができます。
実装
キーワード リスト「黒猫」を既存のテーブルに追加します。
したがって、このキーワード リストを単語に分解すると、「黒」、「怒り」、「猫」が得られます。
通常、キーワード リストを既存のテーブルに挿入し、新しく作成された行の ID を取得します。たとえば、1701 とします。
ここで、"ancillary" と呼ばれる新しいテーブルに単語を挿入します。このテーブルには、プライマリ テーブルのキーワード行 ID、単一の単語、およびその単語の単語リストのサイズのみが含まれます。
テーブル行 1701 に全部で 3 つの単語を挿入することがわかっているので、size=3 で、これらのタプルを挿入します。
(1701, 3, 'black')
(1701, 3, 'cat')
(1701, 3, 'angry')
(これらは独自の一意の ID を受け取りますが、これは私たちには関係ありません)。
しばらくして、次の文を受け取ります。
'Schroedinger cat is black and angry'
最初に、「is」や「and」など、削除するヌル単語のリストに対してクエリを実行できます。しかし、これは必要ありません。
次に、単語と同じ数のクエリを実行して、「Schroedinger」を含む行がどこにもないことを発見し、それを削除できます。しかし、これも必要ではありません。
最後に、補助に対する実際のクエリを作成します。
SELECT KeywordID, COUNT(*) AS total, ListSize*100/COUNT(*) AS match
FROM ancillary WHERE Word IN ('Schroedinger','cat','is','black','and','angry')
GROUP BY KeywordID;
はWHERE
、たとえば次の行を返します。
(1234, 'black') -- from 'black cat'
(1234, 'cat') -- from 'black cat'
(1423, 'angry') -- from 'angry birds'
(1701, 'cat') -- from 'black angry cat'
(1701, 'angry') -- from 'black angry cat'
(1701, 'black') -- from 'black angry cat'
(1999, 'cat') -- from 'nice white cat'
そのため、GROUP はKeywordID
これらの行のカーディナリティを返します。
1423 1 50%
1701 3 100%
1234 2 100%
1999 1 33%
これで、一致率の降順で並べ替え、次にリスト サイズの降順で並べ替えることができます (3 つの単語の 100% の一致は 2 つの単語の 100% の一致よりも優れており、2 つの単語の 1 つに一致することは 3 つの単語の 2 つに一致することよりも優れているため):
1701 3 100% -- our best match
1234 2 100% -- second runner
1423 1 50%
1999 1 33%
一致率を追加して、1 つのクエリで最初のテーブルを取得することもできます。
SELECT mytable.*, total, match FROM
mytable JOIN (
SELECT KeywordID, COUNT(*) AS total, ListSize*100/COUNT(*) AS match
FROM ancillary WHERE Word IN ('Schroedinger','cat','is','black','and','angry')
GROUP BY KeywordID
) AS ancil ON (mytable.KeywordID = ancil.KeywordID)
ORDER BY match DESC, total DESC;
最大のコストは、Word
列にインデックスを付ける必要がある「補助」の完全一致です。