Как включить текущую строку в PARTITION BY оконной функции Postgresql - PullRequest
0 голосов
/ 09 октября 2019

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

SELECT
    userid,
    ARRAY_AGG(userid) OVER (
        PARTITION BY userid > 100
    ) arr,
    AVG(userid) OVER (
        PARTITION BY userid > 100
    ) avg
FROM users;

Я получу это:

 userid |                            arr                            |         avg          
--------+-----------------------------------------------------------+----------------------
     46 | {46,23,69,92}                                             |  57.5000000000000000
     23 | {46,23,69,92}                                             |  57.5000000000000000
     69 | {46,23,69,92}                                             |  57.5000000000000000
     92 | {46,23,69,92}                                             |  57.5000000000000000
    552 | {552,506,575,621,644,667,690,759,713,782,828,460,483,529} | 629.2142857142857143
    ... | ...                                                       | ...
    529 | {552,506,575,621,644,667,690,759,713,782,828,460,483,529} | 629.2142857142857143

Все хорошо, но что, если вместо этого, дляuserids <100, я хотел бы включить каждый userid с единицами> 100:

SELECT
    userid,
    CASE WHEN userid > 100
    THEN ARRAY_AGG(userid) OVER (
        PARTITION BY userid > 100
    )
    ELSE ARRAY_AGG(userid) OVER (
        PARTITION BY userid -- OR userid > 100
        -- PARTITION BY userid > 100 OR CURRENT_ROW
        -- PARTITION BY userid > 100 OR userid = LAG(userid, 0) OVER ()
    )
    END arr
    CASE WHEN userid > 100
    THEN AVG(userid) OVER (
        PARTITION BY userid > 100
    )
    ELSE AVG(userid) OVER (
        PARTITION BY userid -- OR userid > 100
        -- PARTITION BY userid > 100 OR CURRENT_ROW
        -- PARTITION BY userid > 100 OR userid = LAG(userid, 0) OVER ()
    )
    END avg
FROM users;

Весь приведенный выше прокомментированный код - это различные попытки, которые я делал. Лучшее, что у меня есть, это просто идентификатор пользователя без идентификаторов> 100 или все идентификаторы:

 userid |                            arr                            |         avg          
--------+-----------------------------------------------------------+----------------------
     23 | {23}                                                      |  23.0000000000000000
     46 | {46}                                                      |  46.0000000000000000
     69 | {69}                                                      |  69.0000000000000000
     92 | {92}                                                      |  92.0000000000000000
    552 | {552,506,575,621,644,667,690,759,713,782,828,460,483,529} | 629.2142857142857143
    ... | ...                                                       | ...
    529 | {552,506,575,621,644,667,690,759,713,782,828,460,483,529} | 629.2142857142857143

Есть ли способ сделать то, что я ищу? Я также стараюсь не использовать CTE в максимально возможной степени, потому что реальный код так много технической задолженности, что потребуется достаточно много времени, чтобы просто адаптировать его с WITH.

Чтобы быть понятным, здесьожидаемый результат:

 userid |                             arr                              |         avg
--------+--------------------------------------------------------------|----------------------
     23 | {23,552,506,575,621,644,667,690,759,713,782,828,460,483,529} | 588.6000000000000000
     46 | {46,552,506,575,621,644,667,690,759,713,782,828,460,483,529} | 590.1333333333333334
     69 | {69,552,506,575,621,644,667,690,759,713,782,828,460,483,529} | 591.6666666666666667
     92 | {92,552,506,575,621,644,667,690,759,713,782,828,460,483,529} | 593.2000000000000000
    552 | {552,506,575,621,644,667,690,759,713,782,828,460,483,529}    | 629.2142857142857143
    ... | ...                                                          | ...
    529 | {552,506,575,621,644,667,690,759,713,782,828,460,483,529}    | 629.2142857142857143

Вот справочник по потенциальным будущим вещам, на которые я смотрел: вложенные оконные функции (но на данный момент не реализованоPostgresql-11)

РЕДАКТИРОВАТЬ: И последнее, но не менее важное, условие является заполнителем! он может или не может быть привязан к идентификаторам пользователей, он используется здесь только для примера, это могло быть

CUME_DIST() OVER (
    PARTITION BY x -- OR CURRENT_USERID
)

1 Ответ

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

Это отвечает на оригинальную версию вопроса.

Вы, кажется, хотите:

select (case when userid < 100
             then array_cat(array[userid],
                            array_agg(userid) filter (where userid > 100) over ()
             else array_agg(userid) filter (where userid > 100) over ()
        end)
...