SQL-запрос: как выбирать все следующие строки каждый раз, когда конкретный параметр принимает определенное значение
В моей базе данных есть таблица с 3 столбцами: дата и время, параметр, значение. Моя цель - получить часть данных. Я хочу получить все строки, следующие после параметра = 'B' и значения> 5 (включить эту строку в набор результатов). Оставьте все строки, следующие за параметром = 'B' и значением <=5 (включите эту строку в набор результатов).
Другими словами, я хочу использовать VALUE в строках с параметром = B в качестве флага (псевдокода):
include_flag = 0
result_set = empty table
for row in rows:
if parameter = B and value > 5:
result_set.append(row)
include_flag = 1
elif parameter = B and value <= 5:
result_set.append(row)
include_flag = 0
elif parameter <> B:
if include_flag = 1:
result_set.append(row)
elif include_flag = 0:
skip(row)
исходная таблица:
- Какое оптимальное решение этой проблемы (ей)?
Любая помощь будет оценена по достоинству.
1 ответ
Вам необходимо иметь уникальный столбец (id) и использовать « OUTER APPLY » для получения ожидаемых результатов.
Поскольку в ваших данных образца нет уникального столбца, я создал временную таблицу, чтобы создать столбец с уникальным идентификатором и сохранить данные образца.
- Пример ввода:
- создать временную таблицу со столбцом идентификаторов и всеми столбцами из входных данных.
- вставьте входные данные в временную таблицу в порядке date_time, чтобы сохранить порядок данных.
Таблица температуры:
- напишите свой запрос из этой временной таблицы, чтобы сгенерировать столбец B_over_limit и вставить его в другую временную таблицу для дальнейшего использования.
- Теперь напишите запрос с внешним применением, чтобы получить предыдущее значение столбца, когда NULL, чтобы получить окончательный результат.
Запрос:
select * from tb1 --sample source data
order by date_time
--create temp table #t1 (use original table datatypes)
create table #t1
(id int identity not null,
date_time varchar(50),
parameter char(1),
value float
)
insert into #t1 insert input into
select * from tb1 order by convert(datetime,date_time)
select * from #t1;
SELECT id, t.date_time, t.parameter, t.value,
B_over_limit = CASE WHEN t.parameter = 'B' AND t.value > 5.0 THEN 1
WHEN t.parameter = 'B' AND t.value <= 5.0 THEN 0
ELSE null
END
into #t2
FROM #t1 t ORDER BY convert(datetime,t.date_time)
select * from #t2
select a.date_time, a.parameter, a.value,
case when id = 1 and a.B_over_limit is NULL then 0
else ISNULL(a.B_over_limit, t.B_over_limit)
end as B_over_limit
from #t2 a
outer apply
(select top 1 B_over_limit from #t2 b
where b.id < a.id and b.date_time is not null
and b.parameter is not null and b.value is not null
and b.B_over_limit is not null
and a.B_over_limit is null
order by id desc ) t