Postgresql 多对多关系中所有3个表的SELECT语句

Postgresql 多对多关系中所有3个表的SELECT语句,postgresql,postgresql-performance,Postgresql,Postgresql Performance,我在编写包含多对多关系中所有3个表的SELECT查询时遇到问题。我有以下表格: Table "public.companies" Column | Type | Modifiers | Storage | Stats target | Des

我在编写包含多对多关系中所有3个表的
SELECT
查询时遇到问题。我有以下表格:

                                                        Table "public.companies"
     Column     |          Type          |                       Modifiers                        | Storage  | Stats target | Description 
----------------+------------------------+--------------------------------------------------------+----------+--------------+-------------
 id             | integer                | not null default nextval('companies_id_seq'::regclass) | plain    |              | 
 name           | character varying(48)  | not null                                               | extended |              | 
 description    | character varying(512) |                                                        | extended |              | 
 tagline        | character varying(64)  |                                                        | extended |              | 
 featured_image | integer                |                                                        | plain    |              | 
Indexes:
    "companies_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "company_category_associations" CONSTRAINT "company_category_associations_company_id_foreign" FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE CASCADE


                            Table "public.company_category_associations"
   Column    |  Type   |                                 Modifiers                                  
-------------+---------+----------------------------------------------------------------------------
 id          | integer | not null default nextval('company_category_associations_id_seq'::regclass)
 company_id  | integer | not null
 category_id | integer | not null
Indexes:
    "company_category_associations_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "company_category_associations_category_id_foreign" FOREIGN KEY (category_id) REFERENCES company_categories(id) ON DELETE RESTRICT
    "company_category_associations_company_id_foreign" FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE CASCADE


                                  Table "public.company_categories"
   Column    |         Type          |                            Modifiers                            
-------------+-----------------------+-----------------------------------------------------------------
 id          | integer               | not null default nextval('company_categories_id_seq'::regclass)
 name        | character varying(32) | not null
 description | character varying(96) | 
Indexes:
    "company_categories_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "company_category_associations" CONSTRAINT "company_category_associations_category_id_foreign" FOREIGN KEY (category_id) REFERENCES company_categories(id) ON DELETE RESTRICT
我的
公司
表将有大约10万行,一个公司最多可以有10个关联类别。当然,我不会一次选择超过200家公司

我通过以下查询获得了结果:

select 
  c.id as companyid, 
  c.name as companyname, 
  cat.id as categoryid, 
  cat.name as categoryname 
from company_categories cat
  left join company_category_associations catassoc on catassoc.category_id = cat.id
  left join companies c on catassoc.company_id = c.id where c.id is not null;
这个问题源于我需要以JSON格式呈现数据,我希望它如下所示:

{
  "companies": [
    {
      "name": "...",
      "description": "...",
      "categories": [
        {
          "id": 12,
          "name": "Technology"
        },
        {
          "id": 14,
          "name": "Computers"
        },
      ]
    },
    /* ... */
  ]
}
基本上,我希望在尽可能少的查询中获取尽可能多的数据

  • 如何编写
    SELECT
    查询以满足我的需要
  • 我的图表中的数据库结构有问题吗
  • 谢谢大家!


    另外,我正在使用PostgreSQL 9.6.6

    您可以直接从PostgreSQL获取json

    首先定义要输出的复合类型(json对象)。这是为了获取字段的名称,否则它们将被命名为f1、f2、

    create type cat as (id integer, name varchar);
    create type comp as (id integer, name varchar, categories cat[]);
    
    然后选择comps数组和嵌套的cats数组作为json

    select to_json(array(
      select (
        c.id,
        c.name,
        array(
          select (cc.id, cc.name)::cat
          from company_categories cc 
          join company_category_associations cca on (cca.category_id=cc.id and cca.company_id=c.id)
        ))::comp
      from companies c
    )) as companies
    

    您可以嵌套两个JSON聚合以达到目的

    第一级为每个公司创建一个JSON值,类别存储为数组:

    select to_jsonb(c) || jsonb_build_object('categories', jsonb_agg(cc)) comp_json
    from companies c
      join company_category_associations cca on cca.company_id = c.id
      join company_categories cc on cc.id = cca.category_id
    group by c.id;
    
    这将为每个公司返回一行。现在我们需要将这些行聚合为一个JSON值:

    select jsonb_build_object('companies', jsonb_agg(comp_json))
    from (
      select to_jsonb(c) || jsonb_build_object('{categories}', jsonb_agg(cc)) comp_json
      from companies c
        join company_category_associations cca on cca.company_id = c.id
        join company_categories cc on cc.id = cca.category_id
      group by c.id  
    ) t;
    

    在线示例:

    为什么您的关联表有一个
    id
    列?@melpomene该表是由Laravel迁移生成的,我错误地离开了
    id
    列,但我知道拥有它是不合适的there@a_horse_with_no_name请看我的编辑!希望这次它能提供足够的信息