Для столбца, содержащего ngrams в параметре VARCHAR
с utf8mb4_unicode_ci
:
+---------------------------+
| ngram |
+---------------------------+
| Qaru |
| stack |
| overflow |
| Qaru protection |
| overflow protection |
| protection |
+---------------------------+
И запрос:
SELECT * FROM ngrams WHERE ngram IN ('stack', 'stack overflow', 'protection', 'overflow')
Учитывая строки, возвращаемые этим запросом, как я могу хранить только строки с длинными ngrams из возвращенных строк?
В этом примере я получаю 3 строки: stack
, stack overflow
и protection
.
Затем мне нужно отфильтровать строки следующим образом:
- Я отфильтровываю
stack
, потому чтоstack overflow
существует в возвращенных строках - Я сохраняю
stack overflow
, потому что никакая другая возвращенная строка не является ngram, содержащейstack overflow
(в таблице естьQaru protection
, но не в возвращенных строках) - Я продолжаю
protection
- Я отфильтровываю
overflow
, потому чтоstack overflow
существует в возвращенных строках
Это должно быть сделано в MySQL из-за сопоставлений (сравнения вне MySQL не дают таких же результатов, как в MySQL). (Если я не знаю о какой-либо функции MySQL, позволяющей выставить сопоставленную версию строки.)
Я могу придумать следующее решение: (sql скрипта)
SELECT ngram
FROM ngrams n1
WHERE n1.ngram IN ('stack', 'stack overflow', 'protection')
AND NOT EXISTS (
SELECT 1
FROM ngrams n2
WHERE n2.ngram IN ('stack', 'stack overflow', 'protection')
AND LENGTH(n2.ngram) > LENGTH(n1.ngram)
AND CONCAT(' ', n2.ngram, ' ') LIKE CONCAT('% ', n1.ngram, ' %')
)
Это неэффективно, однако, поскольку суб-запрос будет выполняться для каждой согласованной nграммы.
Итак, я ищу
- способ сделать этот запрос эффективным
- или способ сделать это надежно вне MySQL (с учетом сопоставлений)