dt_matrix_tokenテーブルの 2 番目のインスタンスと結合されたdt_matrix_tokenテーブルからのクエリから始めます。ここで、両方のインスタンスには、関心のある値の範囲内のtoken_idがありますが、両方が同じ値を持つことはできません。
それらはまた、一致するstorage_data_idを持つ必要があり(つまり、同じドキュメント内にある)、2 番目のトークンの位置は最初のトークン以上である必要があります。
SELECT mt1.dt_matrix_token_id, mt1.storage_data_id,
mt1.token_id AS token_id1, mt2.token_id AS token_id2,
mt1.position AS position1, mt2.position AS position2
FROM dt_matrix_token AS mt1
JOIN dt_matrix_token AS mt2
WHERE mt1.token_id IN (1,2,3)
AND mt2.token_id IN (1,2,3)
AND mt1.token_id <> mt2.token_id
AND mt1.storage_data_id = mt2.storage_data_id
AND mt2.position >= mt1.position
これにより、関心のある一連のトークンのすべてのペアが得られます。
ここで、最初のテーブルのdt_matrix_token_idでグループ化し、2 番目のテーブルのtoken_idと組み合わせて、最初のテーブルのすべてのトークンに対して、2 番目のテーブルの各token_idの 1 つに結果のセットを絞り込みます。
そして、2 番目のテーブルの結果をグループ化すると、気になるのは最小の順位です。2 番目のトークンは常に最初のトークンの後に続くため、これにより最初のトークンに最も近い位置が得られます。
SELECT mt1.dt_matrix_token_id, mt1.storage_data_id,
mt1.token_id AS token_id1, mt2.token_id AS token_id2,
mt1.position AS position1, MIN(mt2.position) AS position2
FROM dt_matrix_token AS mt1
JOIN dt_matrix_token AS mt2
WHERE mt1.token_id IN (1,2,3)
AND mt2.token_id IN (1,2,3)
AND mt2.token_id <> mt1.token_id
AND mt2.storage_data_id = mt1.storage_data_id
AND mt2.position >= mt1.position
GROUP BY mt1.dt_matrix_token_id, mt2.token_id
これで、関心のあるトークンのすべてのインスタンスについて、同じドキュメント内でそれに続くトークンのいずれかに最も近い位置が得られます。
しかし、本当に必要なのは、最初のトークンからそれに続くトークンまでの最大距離です。したがって、再度dt_matrix_token_idでグループ化し、2 番目の位置の最大値 (つまり、各token_idの最小値の最大値) までの距離を計算する必要があります。
SELECT dt_matrix_token_id, storage_data_id,
MAX(position2)-position1 AS distance
FROM (
SELECT mt1.dt_matrix_token_id, mt1.storage_data_id,
mt1.position AS position1, MIN(mt2.position) AS position2
FROM dt_matrix_token AS mt1
JOIN dt_matrix_token AS mt2
WHERE mt1.token_id IN (1,2,3)
AND mt2.token_id IN (1,2,3)
AND mt2.token_id <> mt1.token_id
AND mt2.storage_data_id = mt1.storage_data_id
AND mt2.position >= mt1.position
GROUP BY mt1.dt_matrix_token_id, mt2.token_id
) AS temp
GROUP BY dt_matrix_token_id
ただし、最初のテーブルのすべてのトークンの後に、関心のある他のすべてのトークンが続くわけではありません。COUNT
したがって、各グループの結果が、対象のトークンの数から 1 を引いた値 (最初のテーブルでは 1 トークン、2 番目のテーブルでは n-1 トークン) に等しいことを確認する必要があります。
HAVING
これは句 --で行うことができますHAVING COUNT(*) = 3-1
。その式の 3 は、検索するトークンの数を表します。
気になるトークンのすべてのインスタンスについて、(同じドキュメント内で) 気になる他のすべてのトークンが後に続く場合、それらすべてをカバーする最短距離が得られます。
しかし、各ドキュメントに対して複数の結果が存在する可能性が非常に高く、実際にはそれぞれのケースで最短のものだけを知る必要があります。そのため、storage_data_idでグループ化し、グループ内の最小距離を計算する必要があります。
SELECT storage_data_id, MIN(distance) AS distance
FROM (
SELECT dt_matrix_token_id, storage_data_id,
MAX(position2)-position1 AS distance
FROM (
SELECT mt1.dt_matrix_token_id, mt1.storage_data_id,
mt1.position AS position1, MIN(mt2.position) AS position2
FROM dt_matrix_token AS mt1
JOIN dt_matrix_token AS mt2
WHERE mt1.token_id IN (1,2,3)
AND mt2.token_id IN (1,2,3)
AND mt2.token_id <> mt1.token_id
AND mt2.storage_data_id = mt1.storage_data_id
AND mt2.position >= mt1.position
GROUP BY mt1.dt_matrix_token_id, mt2.token_id
) AS temp
GROUP BY dt_matrix_token_id
HAVING COUNT(*) = 3-1
) AS temp
GROUP BY storage_data_id
これにより、関心のあるすべてのトークンを含む各ドキュメントと、それらすべてのトークンをカバーする最小距離が得られます。HAVING
結果を特定の範囲の距離に制限するには、別の句を追加するだけです。
HAVING distance <= 20
次に、そのクエリからの結果の数から、指定した範囲内で関心のあるすべてのトークンを含むドキュメントの数がわかります。