Tim*_*imo 9 sql postgresql relational-division jsonb postgresql-9.4
我正在使用PostgreSQL 9.4,其中teams包含一个jsonb名为的列的表json.我正在寻找一个查询,我可以让所有拥有球员的球队3,4以及7他们的球员阵容.
该表包含两行,包含以下json数据:
第一排:
{
"id": 1,
"name": "foobar",
"members": {
"coach": {
"id": 1,
"name": "A dude"
},
"players": [
{
"id": 2,
"name": "B dude"
},
{
"id": 3,
"name": "C dude"
},
{
"id": 4,
"name": "D dude"
},
{
"id": 6,
"name": "F dude"
},
{
"id": 7,
"name": "G dude"
}
]
}
}
Run Code Online (Sandbox Code Playgroud)
第二排:
{
"id": 2,
"name": "bazbar",
"members": {
"coach": {
"id": 11,
"name": "A dude"
},
"players": [
{
"id": 3,
"name": "C dude"
},
{
"id": 5,
"name": "E dude"
},
{
"id": 6,
"name": "F dude"
},
{
"id": 7,
"name": "G dude"
},
{
"id": 8,
"name": "H dude"
}
]
}
}
Run Code Online (Sandbox Code Playgroud)
如何获得所需的团队列表?我已经尝试过一个查询,我会从成员玩家创建一个数组jsonb_array_elements(json -> 'members' -> 'players')->'id'并对它们进行比较,但我所能完成的只是一个结果,其中任何一个比较的玩家ID在一个团队中可用,而不是全部.
Erw*_*ter 13
你一次面临两个非平凡的任务.我很好奇.
jsonb用复杂的嵌套结构.首先,注册一个行类型jsonb_populate_recordset().您可以使用永久创建类型CREATE TYPE,也可以创建临时表以供临时使用(在会话结束时自动删除):
CREATE TEMP TABLE foo(id int); -- just "id", we don't need "name"
Run Code Online (Sandbox Code Playgroud)
我们只需要id,所以不要包括name.每个文件:
将不会在输出中省略未出现在目标行类型中的JSON字段
SELECT t.json->>'id' AS team_id, p.players
FROM teams t
, LATERAL (SELECT ARRAY (
SELECT * FROM jsonb_populate_recordset(null::foo, t.json#>'{members,players}')
)
) AS p(players)
WHERE p.players @> '{3,4,7}';
Run Code Online (Sandbox Code Playgroud)
SQL捣鼓了json在Postgres的9.3(第9.4尚未公布).
使用播放器记录提取JSON数组:
t.json#>'{members,players}'
Run Code Online (Sandbox Code Playgroud)从这些开始,我只使用idwith来排除行:
jsonb_populate_recordset(null::foo, t.json#>'{members,players}')
Run Code Online (Sandbox Code Playgroud)
...并立即将它们聚合成Postgres数组,因此我们在基表中每行保留一行:
SELECT ARRAY ( ... )
Run Code Online (Sandbox Code Playgroud)所有这些都发生在横向连接中:
, LATERAL (SELECT ... ) AS p(players)
Run Code Online (Sandbox Code Playgroud)立即过滤生成的数组,只保留我们要查找的数组 - 使用"contains" 数组运算符@>:
WHERE p.players @> '{3,4,7}'
Run Code Online (Sandbox Code Playgroud)瞧.
如果你在一个大表上经常运行这个查询,你可以创建一个假的IMMUTABLE函数,像上面一样提取数组,并根据这个函数创建函数GIN索引,使这个超级快.
"假"因为函数依赖于基础行类型,即在目录查找上,并且如果更改则会更改.(所以要确保它不会改变.)与此类似:
另外:
不要使用像json列名这样的类型名称(即使这是允许的),这会引发棘手的语法错误和混淆错误消息.
| 归档时间: |
|
| 查看次数: |
4092 次 |
| 最近记录: |