繁体   English   中英

如何 select Postgres 中许多不同表的所有记录,并返回嵌套的数据树?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM