#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;
Замените ?
на вашу строку.
Смотрите упрощенную демонстрацию.