PostgreSQL:让 STRING_AGG 遵守 CTE 的顺序
PostgreSQL: Getting STRING_AGG to respect the ordering from a CTE
我正在创建一个报告,显示工作人员的前团队以及他们离开的日期,汇总到报告中的一个字段中。这在一定程度上起作用:
WITH "most_recent_leave_dates" AS (
SELECT
staff_id, -- alphanumeric string
team,
MAX(date_left) AS "most_recent_date_left"
FROM team_membership
WHERE date_left IS NOT NULL
GROUP BY staff_id, team
-- I thought ordering this CTE would do it, but no
ORDER BY staff_id, most_recent_date_left DESC
)
SELECT
staff_id,
STRING_AGG(
DISTINCT CONCAT(team, ' until ' || most_recent_date_left),
CHR(10) -- separate by newline
) AS "teams"
FROM most_recent_leave_dates
GROUP BY staff_id
https://www.db-fiddle.com/f/jZCcKRWNV8vLJUFsa6kq7/2
但是 STRING_AGG
正在按字母顺序对术语进行排序。我希望它们按 most_recent_date_left
排序。我该怎么做?
documentation 状态:
Alternatively, supplying the input values from a sorted subquery will
usually work.
我是否必须将 CTE 重写为子查询...?
ORDER BY
在 CTE 中没有意义。您可以 ORDER BY
作为 STRING_AGG()
的一部分:
SELECT staff_id,
STRING_AGG(CONCAT(team, ' until ' || most_recent_date_left),
CHR(10)
ORDER BY most_recent_date_left DESC
) AS "teams"
FROM most_recent_leave_dates
GROUP BY staff_id;
只需删除 distinct from outer query 如下(我认为您不需要这个)。您的数据已在 cte 中按 staffid 和 most_recent_date_left.
排序
模式(PostgreSQL v9.6)
CREATE TABLE "team_membership" (
staff_id text,
team text,
date_left date
);
INSERT INTO team_membership VALUES
('aaaa', 'B team', '2019-01-01'),
('aaaa', 'A team', '2021-01-01'),
('aaaa', 'C team', '2020-01-01'),
('aaaa', 'A team', '2018-01-01');
查询#1
WITH "most_recent_leave_dates" AS (
SELECT
staff_id,
team,
MAX(date_left) AS "most_recent_date_left"
FROM team_membership
WHERE date_left IS NOT NULL
GROUP BY staff_id, team
)
SELECT
staff_id,
STRING_AGG(
CONCAT(team, ' until ' || most_recent_date_left),
CHR(10) order by most_recent_date_left desc
) AS "teams"
FROM most_recent_leave_dates
GROUP BY staff_id;
staff_id
teams
aaaa
A team until 2021-01-01 C team until 2020-01-01 B team until 2019-01-01
我正在创建一个报告,显示工作人员的前团队以及他们离开的日期,汇总到报告中的一个字段中。这在一定程度上起作用:
WITH "most_recent_leave_dates" AS (
SELECT
staff_id, -- alphanumeric string
team,
MAX(date_left) AS "most_recent_date_left"
FROM team_membership
WHERE date_left IS NOT NULL
GROUP BY staff_id, team
-- I thought ordering this CTE would do it, but no
ORDER BY staff_id, most_recent_date_left DESC
)
SELECT
staff_id,
STRING_AGG(
DISTINCT CONCAT(team, ' until ' || most_recent_date_left),
CHR(10) -- separate by newline
) AS "teams"
FROM most_recent_leave_dates
GROUP BY staff_id
https://www.db-fiddle.com/f/jZCcKRWNV8vLJUFsa6kq7/2
但是 STRING_AGG
正在按字母顺序对术语进行排序。我希望它们按 most_recent_date_left
排序。我该怎么做?
documentation 状态:
Alternatively, supplying the input values from a sorted subquery will usually work.
我是否必须将 CTE 重写为子查询...?
ORDER BY
在 CTE 中没有意义。您可以 ORDER BY
作为 STRING_AGG()
的一部分:
SELECT staff_id,
STRING_AGG(CONCAT(team, ' until ' || most_recent_date_left),
CHR(10)
ORDER BY most_recent_date_left DESC
) AS "teams"
FROM most_recent_leave_dates
GROUP BY staff_id;
只需删除 distinct from outer query 如下(我认为您不需要这个)。您的数据已在 cte 中按 staffid 和 most_recent_date_left.
排序模式(PostgreSQL v9.6)
CREATE TABLE "team_membership" (
staff_id text,
team text,
date_left date
);
INSERT INTO team_membership VALUES
('aaaa', 'B team', '2019-01-01'),
('aaaa', 'A team', '2021-01-01'),
('aaaa', 'C team', '2020-01-01'),
('aaaa', 'A team', '2018-01-01');
查询#1
WITH "most_recent_leave_dates" AS (
SELECT
staff_id,
team,
MAX(date_left) AS "most_recent_date_left"
FROM team_membership
WHERE date_left IS NOT NULL
GROUP BY staff_id, team
)
SELECT
staff_id,
STRING_AGG(
CONCAT(team, ' until ' || most_recent_date_left),
CHR(10) order by most_recent_date_left desc
) AS "teams"
FROM most_recent_leave_dates
GROUP BY staff_id;
staff_id | teams |
---|---|
aaaa | A team until 2021-01-01 C team until 2020-01-01 B team until 2019-01-01 |