【发布时间】:2020-10-16 15:23:18
【问题描述】:
以下内容涉及用 python 编写并使用 SQLAlchemy 连接到 postgres (v9.5) 关系数据库的 Web 应用程序后端。
假设我们有两个表:items 和 relations。每个项目都有一个 ID,并且可能与多个其他项目相关。此类关系被持久化在关系表中,该表存储了它自己的 ID、两个相关项的 ID 以及关系的名称。
这是一些示例数据:
items: relations:
id name id item1_id item2_id name
--------------- ----------------------------------
1 car 1 1 2 weight
2 boat 2 1 3 colour
3 bike 3 1 4 age
4 jet-pack 4 5 1 age
5 plane
6 rocket
因此,例如 car 和 bike 是通过颜色相关的。
我正在寻找用于数据库查询的 SQLAlchemy 代码提取,以返回所有 items 以及额外的 derived- 或 pseudo-column包含每个元组的关系数据作为结构数组:
id name relations
---------------------------------------------------------------------------------
1 car [ { 2, weight }, { 3, colour }, { 4, age }, { 5, age } ]
2 boat [ { 1, weight } ]
3 bike [ { 1, colour } ]
4 jet-pack [ { 1, age } ]
5 plane [ { 1, age } ]
6 rocket []
一个好的第一步是在尝试转换为 SQLAlchemy 之前生成 SQL 查询。最接近我已经实现的上述目标:
SELECT i.*,
(SELECT array_agg(row(CASE WHEN r.item1_id=i.id THEN r.item2_id ELSE r.item1_id END, i.name))
AS relations from relations r
WHERE r.item1_id=i.id OR r.item2_id=i.id)
FROM items i ;
但更好一点的是将关系实际输出为 json:
SELECT i.*,
(SELECT jsonb_agg(jsonb_build_object('item', CASE WHEN r.item1_id=i.id THEN r.item2_id ELSE r.item1_id END, 'relation', r.name))
AS relations
FROM relations r
WHERE r.item1_id=i.id OR r.item2_id=i.id)
FROM items i;
产生:
id name relations
---------------------------------------------------------------------------------
1 car [ { "item": 2, "relation": "weight" }, { "item": 3, "relation": "colour" }, { "item": 4, "relation": "age" }, { "item": 5, "relation": "age" } ]
2 boat [ { "item": 1, "relation": "weight" } ]
3 bike [ { "item": 1, "relation": "colour" } ]
4 jet-pack [ { "item": 1, "relation": "age" } ]
5 plane [ { "item": 1, "relation": "age" } ]
6 rocket []
如何在 sqlalchemy 中实现这个子查询?
【问题讨论】:
标签: python python-3.x postgresql sqlalchemy postgresql-9.5