Ian*_*lor 6 sql postgresql json
我希望使用 Postgres 聚合 JSON 对象数组,特别是通过外键将关系列表返回到另一个表。在本例中,它是 auser和 他们的teams。
这是我正在使用的架构:
CREATE TABLE teams (
id TEXT PRIMARY KEY,
...
);
CREATE TABLE users (
id TEXT PRIMARY KEY,
...
);
CREATE TABLE memberships (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL FOREIGN KEY (user_id) REFERENCES users(id),
team_id TEXT NOT NULL FOREIGN KEY (team_id) REFERENCES teams(id)
);
Run Code Online (Sandbox Code Playgroud)
通过以下查询:
SELECT
users.id,
...
CASE
WHEN count(teams.*) = 0
THEN '[]'::JSON
ELSE json_agg(DISTINCT teams.id)
END AS teams
FROM users
LEFT JOIN memberships ON users.id = memberships.user_id
LEFT JOIN teams ON teams.id = memberships.team_id
WHERE users.id = $[userId]
GROUP BY
users.id,
...
Run Code Online (Sandbox Code Playgroud)
我可以得到结果作为 s 的平面数组team_id:
{
id: 'user_1',
...
teams: ['team_1', 'team_2']
}
Run Code Online (Sandbox Code Playgroud)
但我想接收 JSON 对象形式的结果:
{
id: 'user_1',
...
teams: [
{ id: 'team_1' },
{ id: 'team_2' }
]
}
Run Code Online (Sandbox Code Playgroud)
我非常接近:
SELECT
users.id,
...
CASE
WHEN count(teams.*) = 0
THEN '[]'::JSON
ELSE json_agg(json_build_object('id', teams.id))
END AS teams
FROM users
LEFT JOIN memberships ON users.id = memberships.user_id
LEFT JOIN teams ON teams.id = memberships.team_id
WHERE users.id = $[userId]
GROUP BY
users.id,
...
Run Code Online (Sandbox Code Playgroud)
但现在我已经失去了该函数DISTINCT的重复结果删除功能,因此我最终为每个team.
您可以使用子查询来解决此问题,该子查询选择适当的组合,然后聚合到一个json数组中:
SELECT id, json_strip_nulls(json_agg(json_build_object('id', team))) AS teams
FROM (
SELECT DISTINCT user_id AS id, team_id AS team
FROM memberships
WHERE user_id = $[userId]) sub
GROUP BY id;
Run Code Online (Sandbox Code Playgroud)
您可以从表中获取用户 ID 和团队 ID memberships,因此将任一表连接到memberships表中都没有意义(除非您从那些表中获取了未向我们展示的其他字段)。如果您确实想使用其他字段,您可以将JOINs 粘贴回去。
该json_strip_nulls()函数将消除[{"id": null}]出现的情况并将其替换为空[]::json。这是PG 9.5的新功能。这也摆脱了相当丑陋和低效的CASE条款。
| 归档时间: |
|
| 查看次数: |
31178 次 |
| 最近记录: |