SQL, как показать приращение в виде доли от общего прироста - PullRequest
2 голосов
/ 22 октября 2019

Предположим, что у меня есть следующие данные sql

species         date         observations
Bird1           08-09-19          40
Bird1           06-10-19          50
Bird1           11-11-19          60
Bird2           08-09-19          50
Bird2           06-10-19          90
Bird3           06-10-19          10
Bird3           11-11-19          20

, и предположим, что я хочу показать для месяца и вида птицы, каким было постепенное изменение в наблюдениях (по отношению к предыдущему месяцу), как доля общего прироста наблюдений за видами птиц за этот месяц. Учитывая данные примера, я хотел бы получить следующий результат.

species         date         observations      increment_fraction
Bird1           08-09-19          40                    0
Bird1           06-10-19          50                    0.2
Bird1           11-11-19          60                    0.5
Bird2           08-09-19          50                    0
Bird2           06-10-19          90                    0.8
Bird3           06-10-19          10                    0
Bird3           11-11-19          20                    0.5

Позвольте мне объяснить эти результаты. Доли приращения, соответствующие дате 08-09-19, равны 0, поскольку более ранние записи недоступны. Вторая строка имеет долю приращения, равную 0,2, потому что общий прирост в наблюдениях между датой 08-09-19 и 06-10-19 равен 50, а изменение приращения для Bird1 между 08-09-19 и 06-10-19 равно 10. Фракция приращения равна 10/50 = 0,2.

То же самое относится и к третьей строке: общее приращение между датами 06-10-19 и 11-11-19 равно 20, а приращение для Bird1 между датами 06-10-19 и 11-11-19 равно 10. Дробная доля равна 10/20 = 0,5.

Следующий запрос даст мне желаемый результат:

with increments_table as (
select species, date, observations, 
observations - lag(observations, 1, observations) over (partition by species 
order by date) as increment
from species_table),

increment_sums as (
select date, sum(increment) as increment_sum
from increments_table
group by date)

select species, date, observations, increment/increment_sum
from increments_table
join increment_sums
on increments_table.date = increment_sums.date

Но мне было интересно, может ли это бытьнемного компактнее. Я думаю, что он может быть более компактным, поскольку это довольно простая операция, но я не уверен, как.

Вопрос: Есть ли способ сделать это короче?

1 Ответ

1 голос
/ 22 октября 2019

Похоже, что база, которую вы использовали для вычисления приращения, всегда является первой доступной точкой данных, в этом случае одношаговое решение будет:

select species, date, observations, 
(observations / first_value(observations) over (partition by species order by date)) - 1 as increment_fraction
from species_table

Конечно, если ваш столбец observationsявляется целым числом, чем вам может потребоваться привести его к float/double, чтобы вы могли получить значения десятичной дроби.

...