我有一个PostgreSQL映射表,其中包含公司员工之间的关系-团队负责人和团队成员。名为leaders
的表如下所示:
leader_id | employee_id
1 | 15
1 | 21
1 | 26
2 | 76
2 | 41
这两列都是person
表的外键,其中包含name
,dob
等信息。
目标是使用如下数据创建JSON:
{
1: {name: "John Doe",
person_id: 1,
employees: {
15: {name: "Oliver Queen",
person_id: 15
},
21: {name: "Barry Alan",
person_id: 21
},
26: {name: "Solomon Rondon",
person_id: 26
},
}
},
2: {name: "Papi Hans",
person_id: 2,
employees: {
76: {name: "Ashley Young",
person_id: 76
},
41: {name: "Amberly Smith",
person_id: 41
}
}
},
}
通过编写带有两个联接的查询来将person
表中的数据分别连接到leader_id
和employee_id
上,然后逐行迭代结果,我可以轻松地做到这一点创建JSON。
我的问题是是否有一种写查询的方法,以便以可用于JSON格式的格式显示结果,从而使我不必逐行迭代来构建它?如果有的话,那会更有效吗?
答案 0 :(得分:4)
str_extract
SELECT
json_object_agg(person_id, -- 5
-- 4
json_build_object('name', name, 'person_id', person_id, 'employees', employees)
)
FROM (
SELECT
l.leader_id as person_id,
p1.name as name,
json_object_agg(l.employee_id, -- 3
json_build_object('name', p2.name, 'person_id', p2.id) -- 2
) as employees
FROM
leader l
JOIN person p1 ON l.leader_id = p1.id -- 1
JOIN person p2 ON l.employee_id = p2.id
GROUP BY l.leader_id, p1.name
) s
表以获取名称在这种情况下,可以将(4)缩短为
person
答案 1 :(得分:1)
使用此人表:
Table "public.emp"
Column | Type | Collation | Nullable | Default
-----------+---------+-----------+----------+---------
person_id | integer | | not null |
name | text | | not null |
Indexes:
"emp_pkey" PRIMARY KEY, btree (person_id)
Referenced by:
TABLE "leaders" CONSTRAINT "leaders_employee_id_fkey" FOREIGN KEY (employee_id) REFERENCES emp(person_id)
TABLE "leaders" CONSTRAINT "leaders_leader_id_fkey" FOREIGN KEY (leader_id) REFERENCES emp(person_id)
例如,您可以这样查询:
SELECT json_agg(q)
FROM (SELECT le.person_id,
le.name,
json_agg(row_to_json(ee)) AS employees
FROM emp le
JOIN leaders l ON le.person_id = l.leader_id
JOIN emp ee ON ee.person_id = l.employee_id
GROUP BY le.person_id, le.name
) AS q;
json_agg
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
[{"person_id":1,"name":"John Doe","employees":[{"person_id":15,"name":"Oliver Queen"}, {"person_id":21,"name":"Barry Alan"}, {"person_id":26,"name":"Solomon Rondon"}]}, +
{"person_id":2,"name":"Papi Hans","employees":[{"person_id":76,"name":"Ashley Young"}, {"person_id":41,"name":"Amberly Smith"}]}]
(1 row)