[英]How to select all records from many different tables in Postgres, and return a nested tree of data?
我有 9 个表,它们大部分相似(相同的 4 列),但其余列在表之间有所不同:
CREATE TABLE my_namespace_attachment (
object_organization_id bigint,
object_type_id integer,
object_id bigint,
object_property_id integer,
bucket_id integer,
value_hash character varying(255)
);
CREATE TABLE my_namespace_boolean (
object_organization_id bigint,
object_type_id integer,
object_id bigint,
object_property_id integer,
value boolean
);
CREATE TABLE my_namespace_decimal (
object_organization_id bigint,
object_type_id integer,
object_id bigint,
object_property_id integer,
value numeric
);
CREATE TABLE my_namespace_integer (
object_organization_id bigint,
object_type_id integer,
object_id bigint,
object_property_id integer,
value integer
);
CREATE TABLE my_namespace_object_binding (
object_organization_id bigint NOT NULL,
object_type_id integer NOT NULL,
object_id bigint NOT NULL,
object_property_id integer NOT NULL,
value_organization_id bigint NOT NULL,
value_type_id integer NOT NULL,
value_object_id bigint NOT NULL
);
CREATE TABLE my_namespace_property_binding (
object_organization_id bigint,
object_type_id integer,
object_id bigint,
object_property_id integer,
value_organization_id bigint,
value_type_id integer,
value_object_id integer,
value_property_id integer
);
CREATE TABLE my_namespace_string (
object_organization_id bigint,
object_type_id integer,
object_id bigint,
object_property_id integer,
value character varying(255)
);
CREATE TABLE my_namespace_text (
object_organization_id bigint,
object_type_id integer,
object_id bigint,
object_property_id integer,
value text
);
CREATE TABLE my_namespace_timestamp (
object_organization_id bigint,
object_type_id integer,
object_id bigint,
object_property_id integer,
value timestamp without time zone
);
select 所有9个表中匹配特定约束的所有记录的标准方法是什么,并包括每个表的“额外”属性? 问题的第二部分是如何在可能的情况下以嵌套方式返回它(如下所述)。
我基本上希望查询像这样工作:
SELECT * FROM
my_namespace_attachment,
my_namespace_boolean,
my_namespace_decimal,
my_namespace_integer,
my_namespace_object_binding,
my_namespace_property_binding,
my_namespace_string,
my_namespace_text,
my_namespace_timestamp
WHERE object_organization_id = 1
AND object_type_id = 2
AND object_id = 3
AND object_property_id = 4
我想在 JavaScript 中使用这些作为 JSON 记录。 如果这很重要,我正在使用knex.js从 Node.js 进行查询。
理想情况下,我会从 SQL 中获取记录,这些记录以这样的嵌套方式分组:
{
[organization_id]: {
[object_type_id]: {
[object_id]: {
[object_property_id]: {
...remainingProperties
}
}
}
}
}
所以对于object_binding
表,它看起来像:
{
[organization_id]: {
[object_type_id]: {
[object_id]: {
[object_property_id]: {
value_organization_id: something,
value_type_id: something2,
value_object_id: something3,
}
}
}
}
}
或者用具体的数据来证明:
{
17: {
20: {
102: {
193: {
value_organization_id: 14,
value_type_id: 12,
value_object_id: 100,
}
}
}
}
}
这样的事情可能吗? 理想情况下,我可以直接从 SQL 获得最后一个嵌套结构(如果它有效的话)。 如果在 SQL 中效率不高或不可能,我可以取回记录的 arrays 并在 JavaScript 的应用层将其简化为这种结构。 但是主要问题仍然是,我如何查询所有 9 个表并返回它们所有唯一的数据列? 现在我只是在 JavaScript 中进行 9 个查询并减少。 这是最好的方法吗? 即使是这样,我仍然想看看它是如何一次查询所有 9 个的。
第一个问题:如何查询9张表?
您可以创建一个视图,请参阅手册:
CREATE OR REPLACE VIEW my_view
( object_organization_id
, object_type_id
, object_id
, object_property_id
, bucket_id
, value_hash
, boolean_value
, decimal_value
, integer_value
, string_value
, text_value
, timestamp_value
, value_organization_id
, value_type_id
, value_object_id
, value_property_id
)
AS
SELECT a.object_organization_id
, a.object_type_id
, a.object_id
, a.object_property_id
, a.bucket_id
, a.value_hash
, b.boolean_value
, d.decimal_value
, i.integer_value
, s.string_value
, t.text_value
, ts.timestamp_value
, o.value_organization_id
, o.value_type_id
, o.value_object_id
, p.value_property_id
FROM my_namespace_attachment AS a
INNER JOIN my_namespace_boolean AS b USING (object_organization_id, object_type_id, object_id, object_property_id)
INNER JOIN my_namespace_decimal AS d USING (object_organization_id, object_type_id, object_id, object_property_id)
INNER JOIN my_namespace_integer AS i USING (object_organization_id, object_type_id, object_id, object_property_id)
INNER JOIN my_namespace_object_binding AS o USING (object_organization_id, object_type_id, object_id, object_property_id)
INNER JOIN my_namespace_property_binding AS p USING (object_organization_id, object_type_id, object_id, object_property_id, value_organization_id, value_type_id, value_object_id)
INNER JOIN my_namespace_string AS s USING (object_organization_id, object_type_id, object_id, object_property_id)
INNER JOIN my_namespace_text AS t USING (object_organization_id, object_type_id, object_id, object_property_id)
INNER JOIN my_namespace_timestamp AS ts USING (object_organization_id, object_type_id, object_id, object_property_id) ;
然后可以直接查询视图:
SELECT *
FROM my_view
WHERE object_organization_id = 1
AND object_type_id = 2
AND object_id = 3
AND object_property_id = 4 ;
第二个问题:如何将列聚合成唯一的 json 数据?
在您的示例中,缺少双引号,因此它不能是从 postgres 生成的 json 数据。 来自 postgres 的 output 可能是:
{
"17": {
"20": {
"102": {
"193": {
"value_organization_id": 14,
"value_type_id": 12,
"value_object_id": 100,
}
}
}
}
}
得到这种结果的查询可能是这样的:
SELECT jsonb_build_object( object_organization_id :: text ,
jsonb_build_object( object_type_id :: text ,
jsonb_build_object( object_id :: text ,
jsonb_build_object( object_property_id :: text ,
to_jsonb(row(value_organization_id, value_type_id, value_object_id))))))
FROM my_namespace_property_binding
这是创建类似内容的尝试。
没有视野。
带有条件的子查询上只有很多左连接。
SELECT json_build_object ( obj.object_organization_id, json_build_object ( obj.object_type_id, json_build_object ( obj.object_id, json_build_object ( 'props', json_agg(json_build_object ( 'property_id', obj.object_property_id, 'value_organization_id', obj.value_organization_id, 'value_type_id', obj.value_type_id, 'value_object_id', obj.value_object_id, 'value_property_id', obj.value_property_id, 'attachment_bucket_id', attach.bucket_id, 'attachment_hash', attach.value_hash, 'boolean', bool.value, 'decimal', dec.value, 'integer', inte.value, 'string', string.value, 'text', txt.value, 'timestamp', ts.value ) -- property ) -- agg1 ) -- object ) -- type ) -- org ) as json FROM ( SELECT DISTINCT obj.object_organization_id, obj.object_type_id, obj.object_id, prop.object_property_id, prop.value_organization_id, prop.value_type_id, prop.value_object_id, prop.value_property_id FROM my_namespace_object_binding obj INNER JOIN my_namespace_property_binding prop USING (object_organization_id, object_type_id, object_id, object_property_id) WHERE obj.object_organization_id = 1 AND obj.object_type_id = 2 AND obj.object_id = 3 AND prop.object_property_id = 4 ) AS obj LEFT JOIN my_namespace_attachment AS attach USING (object_organization_id, object_type_id, object_id, object_property_id) LEFT JOIN my_namespace_boolean AS bool USING (object_organization_id, object_type_id, object_id, object_property_id) LEFT JOIN my_namespace_decimal AS dec USING (object_organization_id, object_type_id, object_id, object_property_id) LEFT JOIN my_namespace_integer AS inte USING (object_organization_id, object_type_id, object_id, object_property_id) LEFT JOIN my_namespace_string AS string USING (object_organization_id, object_type_id, object_id, object_property_id) LEFT JOIN my_namespace_text AS txt USING (object_organization_id, object_type_id, object_id, object_property_id) LEFT JOIN my_namespace_timestamp AS ts USING (object_organization_id, object_type_id, object_id, object_property_id) GROUP BY obj.object_organization_id, obj.object_type_id, obj.object_id;
| json | |:------------------------------------------------ -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ------------------------------------------- | | {"1": {"2": {"3": {"props": [{"property_id": 4, "value_organization_id": null, "value_type_id": null, "value_object_id": null, "value_property_id": null, "attachment_bucket_id": null, "attachment_hash": null, "boolean": null, "decimal": null, "integer": null, "string": null, "text": null, "timestamp": null} ]}}}} |
db<> 在这里摆弄
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.