Postgresql - Как удалить последний из array_agg () в одном запросе выбора? - PullRequest
1 голос
/ 23 января 2020

У меня есть особые потребности с таблицей ниже

              Table "public.skill_name"
  Column  |  Type   | Collation | Nullable | Default
----------+---------+-----------+----------+---------
 position | integer |           | not null |
 value    | text    |           | not null |
 id       | text    |           | not null |
 skill    | text    |           |          |
Indexes:
    "skill_name.id" UNIQUE, btree (id)
Foreign-key constraints:
    "skill_name_skill_fkey" FOREIGN KEY (skill) REFERENCES skill(id) ON DELETE SET NULL

и некоторыми примерами данных, как показано ниже:

 position |                                         value                                         |             id              |            skill
----------+---------------------------------------------------------------------------------------+-----------------------------+-----------------------------
     1000 | Python                                                                                | ck5bxmk67101790acuf05cikujw | ck5bxmk62101789acuf7pj1qmj6
     2000 | Python Language                                                                       | ck5bxmk69101791acufih7mc6u6 | ck5bxmk62101789acuf7pj1qmj6
     3000 | Stdlib                                                                                | ck5bxmk6c101792acuflzcu2avg | ck5bxmk62101789acuf7pj1qmj6
     4000 | functools                                                                             | ck5bxmk6e101793acuf42ih0evn | ck5bxmk62101789acuf7pj1qmj6
     5000 | lru_cache                                                                             | ck5bxmk6g101794acuf690rjgzp | ck5bxmk62101789acuf7pj1qmj6
     1000 | Python                                                                                | ck5bxysvp102005acuf6unt4cb7 | ck2wk5gba044342xbyaulv17i
     2000 | Python Language                                                                       | ck5bxysvs102012acuf5862l0gx | ck2wk5gba044342xbyaulv17i
     3000 | Python Syntax                                                                         | ck5bxysvu102021acufjcmxi1ij | ck2wk5gba044342xbyaulv17i
     4000 | Classes                                                                               | ck5bxysvx102030acufbaz3kml3 | ck2wk5gba044342xbyaulv17i
     5000 | metaclasses                                                                           | ck5bxysvz102037acufa5lmbuhj | ck2wk5gba044342xbyaulv17i

Требуется создать результат, подобный приведенному ниже (NOTE: The last one group by skill been excluded in column path)

            skill            |                                         path
-----------------------------+---------------------------------------------------------------------------------------
 ck5bxmk62101789acuf7pj1qmj6 | Python,Python Language,Stdlib,functools
 ck2wk5gba044342xbyaulv17i   | Python,Python Language,Python Syntax,Classes

У меня ниже sql, но он не работает, он жалуется more than one row returned by a subquery used as an expression

SELECT
    skill,
    ARRAY_REMOVE(
        ARRAY_AGG(value), 
        (
            SELECT
                skill_name.value
                FROM (
                    SELECT
                        *,
                        skill AS skill_id,
                        LAST_VALUE(position) OVER (
                        PARTITION BY skill
                        ORDER BY position
                        ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
                        ) AS last_pos
                    FROM skill_name
                ) skill_name
                WHERE last_pos=position
                GROUP BY skill_name.value
        )
    ) as path
FROM skill_name
GROUP BY skill;

Я не знаю, как это исправить, кто-нибудь может помочь?

Ответы [ 2 ]

1 голос
/ 23 января 2020

Postgres имеет довольно сложные функции массива. Вам не нужен подзапрос для этого:

select skill,
       (array_agg(value order by position))[1:count(*) - 1] as path
from t
group by skill
1 голос
/ 23 января 2020

Вы можете использовать row_number(), чтобы найти и исключить последнее значение из набора результатов до агрегирования :

select skill, array_agg(value order by position) path
from (
    select t.*, row_number() over(partition by skill order by position desc) rn
    from mytable t
) t
where rn > 1
group by skill
...