сравнение строк python sqlite

#python #sql #sqlite #window-functions #sliding-window

#python #sql #sqlite #окно-функции #скользящее окно

Вопрос:

У меня есть база данных sqlite с несколькими строками в таблице. Один из столбцов содержит строки с произвольным количеством положительных целых чисел, поэтому:

 1: '### ## # # # ## # ##'
2: '# ## # ## # ##'
3: '# # # ## ## ### #'
...
 

Я также получил строку сравнения в своем коде на python, которая также выглядит как ‘### #####’
Строка сравнения также содержит произвольное количество положительных целых чисел.

Теперь, если мы возьмем строку базы данных как ‘a b c d e f’, а нашу строку сравнения как ‘g h i j k’, например, мне нужно проверить, есть ли какие-либо 3 последовательных числа в моей строке сравнения (например, ‘g h i’ или ‘h i j’ или ‘i j k’) также являются последовательными числами в базе данных. Итак, в основном мне нужно проверить для каждой строки в базе данных, если

 'g h i' == 'a b c' or 'g h i' == 'b c d' or ...
 

Это выполнимо с учетом того, как мои данные в настоящее время сохраняются в базе данных, или мне нужно сохранить мои данные любым другим способом. В любом случае, как я могу сделать это с помощью SQL?

Ответ №1:

Я бы предложил другой дизайн для вашей таблицы.

Вместо того, чтобы хранить числа, подобные этому:

grp значение
1 ’10 100 20 5 70′
2 ‘100 20 5 35 3 15’

вы могли бы нормализовать таблицу так, чтобы каждая строка содержала только 1 значение:

ID grp значение
1 1 10
2 1 100
3 1 20
4 1 5
5 1 70
6 2 100
7 2 20
8 2 5
9 2 35
10 2 3
11 2 15

Таким образом, проще объединять последовательные числа (в триплеты или что-то еще), чтобы вы могли проверить, содержатся ли объединенные числа внутри вашей строки.

Создайте таблицу:

 CREATE TABLE tablename(id INTEGER PRIMARY KEY AUTOINCREMENT, grp INTEGER, value INTEGER);
 

и для каждой строки используйте функцию window LEAD() , чтобы получить следующее число и одно после него, чтобы создать объединенный триплет.
Затем вы можете использовать оператор LIKE , чтобы проверить, есть ли триплет в вашей строке:

 WITH cte AS (
  SELECT *, 
          value || ' ' ||
          LEAD(value, 1) OVER (PARTITION BY grp ORDER BY id) || ' ' || 
          LEAD(value, 2) OVER (PARTITION BY grp ORDER BY id) str
  FROM tablename
)
SELECT grp, MAX(' ' || ? || ' ' LIKE '% ' || str || ' %') flag
FROM cte 
GROUP BY grp;
 

Или лучшее масштабируемое решение:

 WITH cte AS (
  SELECT *, 
         CASE WHEN ROW_NUMBER() OVER (PARTITION BY grp ORDER BY id) > 2
           THEN GROUP_CONCAT(value, ' ') OVER (
                    PARTITION BY grp ORDER BY id 
                    ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
                )
         END str
  FROM tablename
)
SELECT grp, MAX(' ' || '6 100 20 5 12 19' || ' ' LIKE '% ' || str || ' %') flag
FROM cte 
GROUP BY grp;
 

Замените ? на вашу строку.

Смотрите упрощенную демонстрацию.