Postgresql - см. Ранее рассчитанный столбец - PullRequest
0 голосов
/ 28 мая 2018

У меня есть несколько таблиц, подобных этим.

create table programming_language(
id                         smallserial primary key,
name                       text not null,
initial_users              integer not null,
initial_release            date not null
);

create table usage_data(
id                                   smallserial primary key,
language_id                          integer references programming_language(id),
percent_users_change                 decimal(5,2),
increase_or_decrease                 boolean default False, -- false indicates decrease
survey_year                          integer not null
);

Теперь у каждого program_language есть начальное количество пользователей, как указано в initial_users таблицы.В поле use_data есть столбецcent_users_change, в котором указывается процентное увеличение или уменьшение количества пользователей за предыдущие годы.Является ли это уменьшением или увеличением, определяется столбцом increment_or_column.Теперь мне нужно сделать запрос и найти количество пользователей в каждом опросе_год.Я написал следующий запрос для достижения этой цели, но я не могу, потому что вы не можете ссылаться на переменную в том же запросе выбора.

select language_id,case when increase_or_decrease=True then percent_users_change+(lag(previ,0)  over(partition by language_id order by survey_year))
              when increase_or_decrease=False then percent_users_change-(lag(previ,0) over(partition by language_id order by survey_year))
              end as previ
from usage_data;

Пример данных:

    +----+-------------+----------------------+----------------------+-------------+
| id | language_id | percent_users_change | increase_or_decrease | survey_year |
+----+-------------+----------------------+----------------------+-------------+
|  1 |           1 |                   10 | True                 |        1991 
|  2 |           1 |                  7.5 | True                 |        1993 |
|  3 |           3 |                 12.5 | True                 |        1996 |
|  4 |           4 |                 8.75 | True                 |        1996 |
+----+-------------+----------------------+----------------------+-------------+

Например, для языка 1, если начальных пользователей 10, для 1991 года, я хочу, чтобы11 (10 + 10% к предыдущему году), а после 1992 года - 11,825 (11 + 7,5% из 11) и т. д.

1 Ответ

0 голосов
/ 28 мая 2018

процентные изменения могут быть рассчитаны от первоначальных пользователей

pct_change(i) = init_users * prod_from_0_i(pct_change)

, где pct_change представлен как 1 +/- percent_users_change / 100

например,

# for language 1, init_users = 10 
1991 (change 10%)  -> 10 * (1.10) = 11 
1993 (change 7.5%) -> 10 * (1.10)(1.075) = 11.825  

Для этого нам нужна агрегатная функция Product, которая не реализована в SQL, однако мы можем реализовать ее с помощью логарифмов, мы можем применить агрегатную функцию SUM.

Это работает из-заследующие тождества:

log(xy) = log(x) + log(y)

, обобщающие это для серии xs

log(xs) = log(x0) + log(x1) + ..., where x0,x1,... <- xs
        = sum(log(x | x <- xs))

и

x = exp(log(x))

, то есть exp & log являются обратными функциями.

Также обратите внимание, что log не определено для 0 и отрицательных значений.

комбинируя эти две тождества, мы получим:

exp(SUM(ln(x) | x <- xs, x > 0)) === prod(xs)

Таким образом, мы можем записатьзапрос в виде:

WITH united AS (
    SELECT 
      EXTRACT(YEAR FROM initial_release) yr
    , id
    , initial_users :: NUMERIC users
    , 1.0 change
    FROM programming_language

    UNION ALL

    SELECT 
      survey_year yr
    , language_id id
    , null
    , case when increase_or_decrease 
        then 1 + (percent_users_change / 100.0)
      else 1 - (percent_users_change / 100.0) end change
    FROM usage_data
)
SELECT yr, id, 
FIRST_VALUE(users) OVER w * EXP(SUM(LN(u.change)) OVER w) users
FROM united u
WINDOW w as (PARTITION BY id ORDER BY yr ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)

, где сначала объединяются начальные данные и более поздние данные об использовании, и вычисляется столбец change, а затем users для последовательных лет вычисляется из начальных users.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...