#sql #sql-server #azure-data-factory
Вопрос:
Для SQL-запроса/хранимой процедуры я ищу сумму пиков заданных значений по типу за определенный период времени. Кроме того, если в течение данного периода времени пик не имеет тенденции к снижению, его не следует учитывать.
Данные, например:
Тип | Сумма | Дата |
---|---|---|
ААА | 10 | 2021-07-11 |
ААА | 15 | 2021-07-11 |
ААА | 20 | 2021-07-11 |
ААА | 25 | 2021-07-11 *Нужен этот пик |
ААА | 20 | 2021-07-11 |
ААА | 15 | 2021-07-11 |
ААА | 10 | 2021-07-11 |
ААА | 15 | 2021-07-11 |
ААА | 20 | 2021-07-11 |
ААА | 25 | 2021-07-11 |
ААА | 30 | 2021-07-11 *Нужно добавить этот пик к предыдущему пику |
ААА | 20 | 2021-07-11 |
ААА | 15 | 2021-07-11 |
ААА | 10 | 2021-07-11 |
BBB | 10 | 2021-07-11 |
BBB | 20 | 2021-07-11 |
BBB | 30 | 2021-07-11 *Нужен этот пик |
BBB | 20 | 2021-07-11 |
BBB | 10 | 2021-07-11 |
ССС | 10 | 2021-07-11 |
ССС | 20 | 2021-07-11 |
ССС | 30 | 2021-07-11 |
ССС | 20 | 2021-07-11 |
ССС | 10 | 2021-07-11 |
ССС | 20 | 2021-07-11 |
ССС | 30 | 2021-07-11 |
ССС | 40 | 2021-07-11 *Этот пик не будет учитываться, потому что нисходящий тренд произойдет на следующий день |
ССС | 30 | 2021-07-12 |
ССС | 20 | 2021-07-12 |
ССС | 10 | 2021-07-12 |
Результаты за данный день 2021-07-11 должны быть:
Тип | Весь |
---|---|
ААА | 55 |
BBB | 30 |
(ССС не включен, так как на данную дату не было нисходящего тренда)
Я даже не совсем уверен, с чего начать, за исключением, возможно, получения значения каждой строки, у которой следующая строка меньше (начинается нисходящий тренд).
Комментарии:
1. . . Таблицы SQL представляют собой неупорядоченные наборы. Без упорядочения строк (возможно, с использованием компонента времени
date
) на этот вопрос невозможно ответить.
Ответ №1:
Позвольте мне предположить, что в вашей date
колонке есть временная составляющая. На самом деле вам нужен явный порядок строк, а даты недостаточно.
Если это так, вы можете использовать lead()
и lag()
:
select t.*
from (select t.*,
lag(amount) over (partition by type, convert(date, date) order by date) as prev_amount,
lead(amount) over (partition by type, convert(date, date) order by date) as next_amount
from t
) t
where prev_amount < amount and amount > next_amount;
Редактировать:
Для окончательного согласования:
select type, sum(amount)
from (select t.*,
lag(amount) over (partition by type, convert(date, date) order by date) as prev_amount,
lead(amount) over (partition by type, convert(date, date) order by date) as next_amount
from t
) t
where prev_amount < amount and amount > next_amount;
group by type;
Комментарии:
1. На самом деле это метка времени, а не просто дата. Извините, я пытался упростить пример. Я задавался вопросом об использовании подхода с запаздыванием и опережением, но не был уверен. Как я могу убедиться, что получаю каждый набор (или каждый «Тип» в примере) и суммирую эти квалифицированные пики?
2. Не следует ли скорее провести второе сравнение
amount > next_amount
, если мы ищем локальный максимум?3. @GordonLinoff, это очень полезно. Большое спасибо.
Ответ №2:
Учитывая текущую структуру таблицы, это невозможно. Вам понадобится, по крайней мере, еще один столбец, чтобы указать порядок каждой записи. В противном случае запрос не гарантирует
AAA 10 2021-07-11
всегда будет приходить раньше
AAA 15 2021-07-11
Нет никакого индикатора, почему второе позже первого.
Комментарии:
1. В реляционной базе данных нет встроенного порядка-вы должны каким — то образом добавить ее сами.
2. Да, в этом есть полный смысл. На самом деле это метка времени, а не просто дата. Я пытался упростить пример, но вы абсолютно правы.