Таблица запросов с array_agg / медиана ВСЕХ предыдущих позиций, LAST_10, LAST_50, исключая текущую позицию - PullRequest
0 голосов
/ 07 мая 2019

Это вариант этого блестяще отвеченного вопроса, который я отправил ранее :

У меня есть таблица базы данных с:

id | date       | position | name
--------------------------------------
1  | 2016-06-29 | 9        | Ben Smith
2  | 2016-06-29 | 1        | Ben Smith
3  | 2016-06-29 | 5        | Ben Smith
4  | 2016-06-29 | 6        | Ben Smith
5  | 2016-06-30 | 2        | Ben Smith
6  | 2016-06-30 | 2        | Tom Brown
7  | 2016-06-29 | 4        | Tom Brown
8  | 2016-06-30 | 2        | Tom Brown
9  | 2016-06-30 | 1        | Tom Brown

Как я могу запросить таблицуэффективно, так что я могу получить новые столбцы с помощью array_agg ().

Я уже пробовал следующий запрос, однако он невероятно медленный и неправильный, поскольку он не группирует предыдущие_позиции по столбцу имени:

 SELECT runners.id AS runner_id,
    btrim(regexp_replace(replace(upper(runners.name::text), '.'::text, ''::text), '[[:digit:]]'::text, ''::text, 'g'::text)) AS name,
    runners.position_two,
    (array_agg(runners.position_two) OVER w AS results
   FROM runners
  WINDOW w AS (PARTITION BY (btrim(regexp_replace(replace(upper(runners.name::text), '.'::text, ''::text), '[[:digit:]]'::text, ''::text, 'g'::text))) ORDER BY runners.id ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING);

Я ожидаю, что вывод таблицы будет выглядеть следующим образом

id | date       | position | name      | previous   | med  |med_20
----------------------------------------------------------------------
1  | 2016-06-29 | 9        | Ben Smith | {}         |      |
2  | 2016-06-29 | 1        | Ben Smith | {9}        | 9    | 9
3  | 2016-06-29 | 5        | Ben Smith | {9,1}      | 5    | 5
4  | 2016-06-29 | 6        | Ben Smith | {9,1,5}    | 5    | 5
5  | 2016-06-30 | 2        | Ben Smith | {9,1,5,6}  | 5.5  | 5.5
6  | 2016-06-30 | 2        | Tom Brown | {}         | None | None
7  | 2016-06-29 | 4        | Tom Brown | {2}        | 2    | 2
8  | 2016-06-30 | 2        | Tom Brown | {2,4}      | 3    | 3
9  | 2016-06-30 | 1        | Tom Brown | {2,4,2}    | 2    | 2

1 Ответ

0 голосов
/ 07 мая 2019

Postgres не имеет встроенной функции агрегирования для MEDIAN. Но вы можете создать его, используя фрагмент функции, доступный в Postgres wiki . Этот фрагмент также является частью пользовательской библиотеки ulib_agg .

После создания вы можете использовать его как любую агрегатную функцию, например SUM или STRING_AGG с аналогичной спецификацией window. Postgres предоставляет вам возможность указать несколько window определений для агрегатных функций, разделенных запятой.

Итак, чтобы получить MEDIAN из предыдущих 20 записей, ваше окно может быть определено как в этом запросе.

SELECT 
j.* ,  array_agg(position) over w as previous_positions,
       median(position)    over w_20 as med_20
  FROM jockeys j
WINDOW w as
(  partition by name ORDER BY id rows between 
     unbounded preceding and 1 preceding
     ),
     w_20 as
     (  partition by name ORDER BY id rows between 
           20 preceding and 1 preceding
     )

Кроме того, вы можете применить функцию ROUND, если хотите обрезать десятичные цифры.

DEMO

...