В БД есть таблица в два столбца с большим количеством записей. Первый столбец - 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