Существует ли не грубая сила/эффективный способ определения минимального значения, поддерживаемого в течение x минут из таблицы sql со структурой, как показано ниже? Эта таблица будет иметь 1 запись на case_id за канал_индекса в секунду, и в этой таблице может быть 20 каналов на каждый случай и тысячи случаев. Мне нужно будет выполнить этот запрос для каждого случая и для каждого канала. Мне нужно найти наименьшее и самое высокое значение, которое произошло в течение 3 последовательных минут.Как найти наименьшее устойчивое значение
value_duration уже рассчитан, чтобы сделать эти типы запросов несколько быстрее. Он находится в секундах и может быть полностью случайным. Это указывает время между последовательными показаниями, полученными от канала.
case_id channel_index start_time dms_value value_duration
----------- ------------- ----------------------- ---------------------- --------------
2668 0 2011-09-28 10:24:39.000 69.5769729614258 2
2668 0 2011-09-28 10:24:41.000 69.7469329833984 2
2668 0 2011-09-28 10:24:43.000 69.8547210693359 1
2668 0 2011-09-28 10:24:44.000 69.8475494384766 1
2668 0 2011-09-28 10:24:45.000 69.9703216552734 2
2668 0 2011-09-28 10:24:47.000 69.9699172973633 1
2668 0 2011-09-28 10:24:48.000 70.0099258422852 2
2668 0 2011-09-28 10:24:50.000 70.2449035644531 1
2668 0 2011-09-28 10:24:51.000 70.0424575805664 2
2668 0 2011-09-28 10:24:53.000 70.1216125488281 1
2668 0 2011-09-28 10:24:54.000 69.5616912841797 1
2668 0 2011-09-28 10:24:55.000 69.5902786254883 2
2668 0 2011-09-28 10:24:57.000 70.0330581665039 1
2668 0 2011-09-28 10:24:58.000 70.4709854125977 1
2668 0 2011-09-28 10:24:59.000 70.7001647949219 2
2668 0 2011-09-28 10:25:01.000 70.274040222168 1
2668 0 2011-09-28 10:25:02.000 69.7524795532227 1
2668 0 2011-09-28 10:25:03.000 69.4606552124023 2
2668 0 2011-09-28 10:25:05.000 69.6096954345703 1
2668 0 2011-09-28 10:25:06.000 69.8238906860352 1
Я надеюсь, не придется бежать через тестирование контура для значения, увеличивающиеся, а затем проверить на следующий, и так далее.
Например, из приведенного выше набора данных, если бы я хотел знать наименьшее значение в течение 5 последовательных секунд, это будет 69.8238906860352. Если бы мне это понадобилось в течение 8 последовательных секунд, это было бы 69.9703216552734.
Вот полная структура таблицы:
CREATE TABLE [dbo].[continuous_data](
[case_id] [int] NOT NULL,
[channel_index] [smallint] NOT NULL,
[start_time] [datetime] NOT NULL,
[dms_type] [char](1) NOT NULL,
[dms_value] [float] NOT NULL,
[value_duration] [smallint] NOT NULL,
[error_code] [int] NULL
) ON [PRIMARY]
EDIT 3-5-12: SO я реализовал грубую силу так, чтобы вычислить минимальные устойчивые значения и, кажется, работает хорошо, когда конкретный случай имеет несколько тысяч записей, но при тестировании на случай, который имел 1,1 миллиона, я закончил отмену его через 37 минут ... Вот код, который я использую. У кого-нибудь есть идеи по оптимизации?
ALTER procedure [dbo].[GetSustainedValues](
@case_id int,
@time_limit int,
@bypass_only bit = NULL)
as
begin
DECLARE @time DateTime, @channelindex int, @lastchannelindex int
DECLARE @tmin float, @tmax float, @min float, @max float, @caseid int
DECLARE @results TABLE(case_id int, channel_index int, max float null, min float null)
DECLARE CursorName CURSOR FAST_FORWARD
FOR SELECT start_time, channel_index from continuous_data where case_id = @case_id order by channel_index, start_time
OPEN CursorName
FETCH NEXT FROM CursorName INTO @time, @channelindex
SET @lastchannelindex = @channelindex
WHILE @@FETCH_STATUS = 0
BEGIN
--PRINT 'hello' --'Chennel:' + CONVERT (VARCHAR(50), @channelindex,128) + ' Time:' + CONVERT (VARCHAR(50), @time,128)
IF @lastchannelindex != @channelindex
BEGIN
--PRINT 'Starting new channel:' + CONVERT (VARCHAR(50), @channelindex,128)
-- we are starting on a new channel so insert that data into the results
-- table and reset the min/max
INSERT INTO @results(case_id, channel_index, max, min) VALUES(@case_id, @lastchannelindex, @max, @min)
SET @max = null
SET @min = null
SET @lastchannelindex = @channelindex
END
Select @tmax = MAX(dms_value), @tmin = MIN(dms_value)
from continuous_data
where case_id = @case_id and channel_index = @channelindex and start_time between DATEADD(s, -(@time_limit-1), @time) and @time
HAVING SUM(value_duration) >= @time_limit
IF @@ROWCOUNT > 0
BEGIN
IF @max IS null OR @tmin > @max
BEGIN
--PRINT 'Setting max:' + CONVERT (VARCHAR(50), @tmin,128) + ' for channel:' + CONVERT (VARCHAR(50), @channelindex,128)
set @max = @tmin
END
IF @min IS null OR @tmax < @min
BEGIN
set @min = @tmax
END
END
--PRINT 'Max:' + CONVERT (VARCHAR(50), @max,128) + ' Min:' + CONVERT (VARCHAR(50), @min,128)
FETCH NEXT FROM CursorName INTO @time, @channelindex
END
CLOSE CursorName
DEALLOCATE CursorName
--PRINT 'Max:' + CONVERT (VARCHAR(50), @max,128) + ' Min:' + CONVERT (VARCHAR(50), @min,128)
SELECT * FROM @results
end
EDIT: 3-7-2012 До сих пор не нашли ответа. Есть ли более эффективный способ сделать это, используя DLL .Net, которая может быть вызвана из хранимой процедуры? Ищите любые предложения здесь. Благодаря!
Является ли продолжительность продолжительности в минутах, и всегда ли она 1 или 2? – Phil
№ Значение value может быть любым. Набор выборочных данных, который я выбрал, имеет только 1 или 2. Это просто разница во времени между выборками в секундах. – mdutra
Когда вы говорите наименьшее устойчивое значение, вы имеете в виду, что dms_value должно быть равно или ниже в течение всего времени? – Martin