SQLite запрос, чтобы получить похожие предложения - PullRequest
0 голосов
/ 05 октября 2019

ТАБЛИЦА животных

id | txt
1  | cat dog parrot pig ant wolf pigeon robin
2  | fox mole dog weasel cat swan bee
3  | duck heron dog ant dog fly moth fox

У меня есть строка, например cat parrot fox bee mole dog weasel, и мне нужен процентный результат, например:

2 | 5/7 words found, 71.4%
1 | 3/7 words found, 42.9%
3 | 2/7 words found, 28,6%

Мое реальное решение заключается вquery

SELECT animals_id, animals_txt FROM animals
          WHERE (INSTR(animals_txt, 'cat') > 0 OR
                 INSTR(animals_txt, 'parrot') > 0 OR
                 INSTR(animals_txt, 'fox') > 0 OR
                 INSTR(animals_txt, 'bee') > 0 OR
                 INSTR(animals_txt, 'mole') > 0 OR
                 INSTR(animals_txt, 'dog') > 0 OR
                 INSTR(animals_txt, 'weasel') > 0)
          ORDER BY random()"

Затем проверьте этот массив ключевых слов {cat|parrot|fox|bee|mole|dog|weasel} по всем результатам и создайте массив результатов на основе процентов, например:

id | percentage
55 | 97
87 | 89
19 | 49

Хотел бы использовать COUNT(),но не привык к этому. База данных насчитывает около 90 000 строк. Есть ли лучшее решение?

1 Ответ

1 голос
/ 05 октября 2019

Независимо от того, считаете ли вы, что лучше, решать вам, но, возможно, рассмотрите следующее, которое дает желаемые результаты одним ударом. Обратите внимание, что проводится более конкретная проверка, т. Е. Пробел до или после слова требуется, поэтому сом не считается кошкой.

  • Обратите внимание, что, если мне не нужно повторно посетить оптику, кажется, что 1 имеет 6не 5 хитов

Пример: -

 WITH f(found,id,txt) AS (
    SELECT
        CASE WHEN instr(' '||txt||' ',' cat ') > 0 THEN 1 ELSE 0 END +
        CASE WHEN instr(' '||txt||' ',' parrot ') > 0 THEN 1 ELSE 0 END +
        CASE WHEN instr(' '||txt||' ',' fox ') > 0 THEN 1 ELSE 0 END +
        CASE WHEN instr(' '||txt||' ',' bee ') > 0 THEN 1 ELSE 0 END +
        CASE WHEN instr(' '||txt||' ',' mole ') > 0 THEN 1 ELSE 0 END +
        CASE WHEN instr(' '||txt||' ',' dog ') > 0 THEN 1 ELSE 0 END +
        CASE WHEN instr(' '||txt||' ',' weasel ')> 0 THEN 1 ELSE 0 END,
        id,
        txt
    FROM animals
    )
SELECT found||'/7 words found, '|| round(found / (7.0 / 100.00),1)||'%' AS result FROM f;
  • С позволяет создать CTE ( C ommon T способный E xpression, временная таблица как таковая) или несколько CTE. CTE был назван f, который в основном является результатом запроса, который получает существующие строки, и строкой found , которая является накоплением хитов (ключевых слов, найденных в предложении). f затем используется в основном запросе, чтобы получить количество совпадений и процент попаданий.

Результат: -

enter image description here

Дополнительно

Вместо СЛУЧАЯ, КОГДА ДРУГОЙ КОНЕЦ, как используетсявыше можно использовать следующее для получения количества попаданий (возможно, есть несколько способов добиться того же результата): -

    (instr(' '||txt||' ',' cat ') > 0) + 
    (instr(' '||txt||' ',' parrot ') > 0) + 
    (instr(' '||txt||' ',' fox ') > 0) + 
    (instr(' '||txt||' ',' bee ') > 0) +
    (instr(' '||txt||' ',' mole ') > 0) +
    (instr(' '||txt||' ',' dog ') > 0) +
    (instr(' '||txt||' ',' weasel ') > 0)

Более гибкая версия

Вот адаптация, гдесписок животных для проверки cat parrot fox bee mole dog weasel может быть изменен, позволяя составить список до 20 животных. Обратите внимание, что важно, чтобы за последним животным следовал пробел, иначе последнее не будет учитываться.

WITH RECURSIVE
    /* 1st CTE keywords extracted from input variable */ 
    k(counter,kword,rest) AS 
        (
            SELECT 
                0, /* start counter 0 because  first row will have no keyword */
                '', /* dummy first keyword (required as column counts must match for UNION) */
                'cat parrot fox bee mole dog weasel ' /* <<<<<<<<< list of animals to search for */
                -- '' /* used to test to items to search for therefore commented out */
            UNION ALL SELECT counter+1,substr(rest,1,instr(rest,' ')),substr(rest,instr(rest,' ') +1) FROM k LIMIT 21
        ),
    /* 2nd CTE remove the row where the keyword is empty */
    kc AS 
        (
            SELECT counter, kword FROM k WHERE length(kword) > 0
        ),
    /* 3rd CTE count the occurences (hits) of the keywords for each row in the animals table */
    f(found,id,txt) AS 
        (
            SELECT 
                CASE WHEN (SELECT count() FROM kc) >= 1 AND instr(' '||txt||' ',(SELECT kword FROM kc WHERE counter = 1)) > 1 THEN 1 ELSE 0 END +
                CASE WHEN (SELECT count() FROM kc) >= 2 AND instr(' '||txt||' ',(SELECT kword FROM kc WHERE counter = 2)) > 1 THEN 1 ELSE 0 END +
                CASE WHEN (SELECT count() FROM kc) >= 3 AND instr(' '||txt||' ',(SELECT kword FROM kc WHERE counter = 3)) > 1 THEN 1 ELSE 0 END +
                CASE WHEN (SELECT count() FROM kc) >= 4 AND instr(' '||txt||' ',(SELECT kword FROM kc WHERE counter = 4)) > 1 THEN 1 ELSE 0 END +
                CASE WHEN (SELECT count() FROM kc) >= 5 AND instr(' '||txt||' ',(SELECT kword FROM kc WHERE counter = 5)) > 1 THEN 1 ELSE 0 END +
                CASE WHEN (SELECT count() FROM kc) >= 6 AND instr(' '||txt||' ',(SELECT kword FROM kc WHERE counter = 6)) > 1 THEN 1 ELSE 0 END +
                CASE WHEN (SELECT count() FROM kc) >= 7 AND instr(' '||txt||' ',(SELECT kword FROM kc WHERE counter = 7)) > 1 THEN 1 ELSE 0 END +
                CASE WHEN (SELECT count() FROM kc) >= 8 AND instr(' '||txt||' ',(SELECT kword FROM kc WHERE counter = 8)) > 1 THEN 1 ELSE 0 END +
                CASE WHEN (SELECT count() FROM kc) >= 9 AND instr(' '||txt||' ',(SELECT kword FROM kc WHERE counter = 9)) > 1 THEN 1 ELSE 0 END +
                CASE WHEN (SELECT count() FROM kc) >= 10 AND instr(' '||txt||' ',(SELECT kword FROM kc WHERE counter = 10)) > 1 THEN 1 ELSE 0 END +
                CASE WHEN (SELECT count() FROM kc) >= 11 AND instr(' '||txt||' ',(SELECT kword FROM kc WHERE counter = 11)) > 1 THEN 1 ELSE 0 END +
                CASE WHEN (SELECT count() FROM kc) >= 12 AND instr(' '||txt||' ',(SELECT kword FROM kc WHERE counter = 12)) > 1 THEN 1 ELSE 0 END +
                CASE WHEN (SELECT count() FROM kc) >= 13 AND instr(' '||txt||' ',(SELECT kword FROM kc WHERE counter = 13)) > 1 THEN 1 ELSE 0 END +
                CASE WHEN (SELECT count() FROM kc) >= 14 AND instr(' '||txt||' ',(SELECT kword FROM kc WHERE counter = 14)) > 1 THEN 1 ELSE 0 END +
                CASE WHEN (SELECT count() FROM kc) >= 15 AND instr(' '||txt||' ',(SELECT kword FROM kc WHERE counter = 15)) > 1 THEN 1 ELSE 0 END +
                CASE WHEN (SELECT count() FROM kc) >= 16 AND instr(' '||txt||' ',(SELECT kword FROM kc WHERE counter = 16)) > 1 THEN 1 ELSE 0 END +
                CASE WHEN (SELECT count() FROM kc) >= 17 AND instr(' '||txt||' ',(SELECT kword FROM kc WHERE counter = 17)) > 1 THEN 1 ELSE 0 END +
                CASE WHEN (SELECT count() FROM kc) >= 18 AND instr(' '||txt||' ',(SELECT kword FROM kc WHERE counter = 18)) > 1 THEN 1 ELSE 0 END +
                CASE WHEN (SELECT count() FROM kc) >= 19 AND instr(' '||txt||' ',(SELECT kword FROM kc WHERE counter = 19)) > 1 THEN 1 ELSE 0 END +
                CASE WHEN (SELECT count() FROM kc) >= 20 AND instr(' '||txt||' ',(SELECT kword FROM kc WHERE counter = 20)) > 1 THEN 1 ELSE 0 END
                ,id,txt
            FROM animals
        )
/* Output the results as per hits from the final CTE */
SELECT 
    *, 
    ifnull(
        found||' out of '
            ||(SELECT count() FROM kc)
            ||' words found, '
            || round(found / (CAST((SELECT count() FROM kc) AS REAL) / 100.00),1) 
            ||'%',

        /* handle no animals to search for */
        'No Animals to search for!'
    )
    AS result 
FROM f 
ORDER BY random()
;

Результаты

Обратите внимание, что в таблицу животных добавлено 3 дополнительных строкиявляется пустой строкой '', вторая - NULL, третья - это список животных, ни одно из которых не ищется согласно 'kcud noreh god tna god ylf htom xof'.

Список животных для поиска соответствует запросу (добавленопробел) то есть 'cat parrot fox bee mole dog weasel ', это приводит к: -

enter image description here

Если список для поиска изменяется, скажем, 'cat parrot fox bee mole dog weasel snake leopard elephant moose flea unicorn gnat butterfly flutterby gutterfly horse hare rabbit giraffe ' /* <<<<<<<<< list of animals to search for */ 21животных , тогда результат: -

enter image description here

  • Из-за а) LIMIT 21 (самая первая строка будет пустым ключевым словом, поэтому она будет отброшена CTE2), а затем б) операторы CASE обслуживают только 20 ключевых слов.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...