Kok*_*zzu 24 postgresql join json postgresql-9.4
我有这个 SQL:
CREATE TABLE test(id SERIAL PRIMARY KEY, data JSONB);
INSERT INTO test(data) VALUES
('{"parent":null,"children":[2,3]}'),
('{"parent":1, "children":[4,5]}'),
('{"parent":1, "children":[]}'),
('{"parent":2, "children":[]}'),
('{"parent":2, "children":[]}');
Run Code Online (Sandbox Code Playgroud)
那会给:
id | data
----+--------------------------------------
1 | {"parent": null, "children": [2, 3]}
2 | {"parent": 1, "children": [4, 5]}
3 | {"parent": 1, "children": []}
4 | {"parent": 2, "children": []}
5 | {"parent": 2, "children": []}
Run Code Online (Sandbox Code Playgroud)
当进行正常的一对多时,它会显示如下内容:
SELECT *
FROM test x1
LEFT JOIN test x2
ON x1.id = (x2.data->>'parent')::INT;
id | data | id | data
----+--------------------------------------+----+-----------------------------------
1 | {"parent": null, "children": [2, 3]} | 2 | {"parent": 1, "children": [4, 5]}
1 | {"parent": null, "children": [2, 3]} | 3 | {"parent": 1, "children": []}
2 | {"parent": 1, "children": [4, 5]} | 4 | {"parent": 2, "children": []}
2 | {"parent": 1, "children": [4, 5]} | 5 | {"parent": 2, "children": []}
5 | {"parent": 2, "children": []} | |
4 | {"parent": 2, "children": []} | |
3 | {"parent": 1, "children": []} | |
Run Code Online (Sandbox Code Playgroud)
如何根据孩子加入(使用LEFT JOIN或WHERE IN)?我试过了:
SELECT data->>'children' FROM test;
?column?
----------
[2, 3]
[4, 5]
[]
[]
[]
SELECT json_array_elements((data->>'children')::TEXT) FROM t...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
SELECT json_array_elements((data->>'children')::JSONB) FROM ...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
SELECT json_to_record((data->>'children')::JSON) FROM test;
ERROR: function returning record called in context that cannot accept type record
HINT: Try calling the function in the FROM clause using a column definition list.
SELECT * FROM json_to_record((test.data->>'children')::JSON);
ERROR: missing FROM-clause entry for table "test"
LINE 1: SELECT * FROM json_to_record((test.data->>'children')::JSON)...
Run Code Online (Sandbox Code Playgroud)
Erw*_*ter 26
这会更有效率:
jsonb和jsonb_array_elements_text()在第 9.4+ 页EXPLAIN
SELECT p.id AS p_id, p.data
, c.id AS c_id, c.data
FROM test p
LEFT JOIN LATERAL jsonb_array_elements_text(p.data->'children') pc(child) ON TRUE
LEFT JOIN test c ON c.id = pc.child::int;Run Code Online (Sandbox Code Playgroud)
db<>在这里摆弄
关于jsonb_array_elements_text():
使用->运算符而不是->>在对 的引用中children。你拥有它的方式,你首先将json/投射jsonb 到text,然后再回到json.
调用集合返回函数的干净方法是LEFT [OUTER] JOIN LATERAL. 这包括没有孩子的行。要排除这些,请更改为[INNER] JOIN LATERALor CROSS JOIN- 或带逗号的速记语法:
, json_array_elements(p.data->'children') pc(child)
Run Code Online (Sandbox Code Playgroud)
避免结果中出现重复的列名。
json和json_array_elements()在第 9.3 页SELECT p.id AS p_id, p.data AS p_data
, c.id AS c_id, c.data AS c_data
FROM test p
LEFT JOIN LATERAL json_array_elements(p.data->'children') pc(child) ON TRUE
LEFT JOIN test c ON c.id = pc.child::text::int;
Run Code Online (Sandbox Code Playgroud)
旁白:标准化的数据库设计,基本数据类型将是方式这更有效。
| 归档时间: |
|
| 查看次数: |
47285 次 |
| 最近记录: |