Страницы

Поиск по вопросам

пятница, 16 ноября 2018 г.

Поиск последовательности в таблице

В БД есть таблица в два столбца с большим количеством записей. Первый столбец - id, второй - числа с плавающей точкой.
Дана последовательность трёх чисел с плавающей точкой. Нужно узнать, встречается ли такая последовательность в БД - допустим с 10 id по 12. Если есть - то нужен id начального числа.
Как это лучше всего сделать с наименьшими энергозатратами? Выбрать в массив вхождения по первому числу и в затем цикле проверить остальные 2? Но записей в ней очень много - такая переборка займёт большое время.
Дополню, чтобы понятней задача была. Вот БД:
4.3422 5.3434 3.3243 4.2453 2.3445 и т.д.
Дана последовательность 3х чисел: 5.3434, 3.3243, 4.2453. Нужно найти эту последовательность в базе данных - есть ли она вообще, а если есть, то вернуть что они находятся в том же порядке со 2 id по 4.


Ответ

Стандартная задача на поиск подпоследовательности в последовательности. Далее два запроса, которые ищут все вхождения подпоследовательности в последовательность:
1) вариант для подпосл. из 3х элементов. работает только если в Id нет пропусков значений.
2) для любых подпоследовательностей.
DECLARE @T1 TABLE(Id INT, Value MONEY) DECLARE @T2 TABLE(Id INT, Value MONEY) INSERT @T1 VALUES (1,1),(2,2),(3,3),(4,4),(5,3), (6,2),(7,3),(8,4),(9,3),(10,2) INSERT @T2 VALUES (1,2),(2,3),(3,4)
--вариант для трёх, работает только если в Id нет пропусков значений. SELECT MIN(T1.Id) Id FROM @T1 T1 JOIN @T2 T2 ON T1.Value = T2.Value GROUP BY T1.Id - T2.Id HAVING COUNT(*) = 3
--более общий вариант, работает с любыми последовательностями SELECT MIN(T1.Id) Id FROM (SELECT ROW_NUMBER()OVER(ORDER BY Id)N,* FROM @T1)T1 JOIN (SELECT ROW_NUMBER()OVER(ORDER BY Id)N,COUNT(*)OVER()C,* FROM @T2)T2 ON T1.Value = T2.Value GROUP BY T1.N - T2.N HAVING COUNT(*)=MAX(C)
UPD: если вы заранее знаете все три значения, то пожалуй лучше встроить конструктор таблицы прямо в запрос. Ещё 2 варианта:
DECLARE @T1 TABLE(Id INT, Value MONEY) INSERT @T1 VALUES (1,1),(2,2),(3,3),(4,4),(5,3), (6,2),(7,3),(8,4),(9,3),(10,2) DECLARE @Param1 MONEY = 2, @Param2 MONEY = 3, @Param3 MONEY = 4
--В столбце Id таблички @T1 нет пропусков: SELECT MIN(T1.Id) Id FROM @T1 T1 JOIN (VALUES(1,@Param1),(2,@Param2),(3,@Param3))T2(Id, Value) ON T1.Value = T2.Value GROUP BY T1.Id - T2.Id HAVING COUNT(*)=3
--В столбце Id таблички @T1 есть пропуски: SELECT MIN(T1.Id) Id FROM (SELECT ROW_NUMBER()OVER(ORDER BY Id)N,* FROM @T1)T1 JOIN (VALUES(1,@Param1),(2,@Param2),(3,@Param3))T2(N, Value) ON T1.Value = T2.Value GROUP BY T1.N - T2.N HAVING COUNT(*)=3

Комментариев нет:

Отправить комментарий