簡體   English   中英

我將如何加入MySQL中的兩個表(多對一)並獲得特定的JSON output(如下圖)

[英]How would I join two tables in MySQL (many to one) and get a specific JSON output (as shown below)

我將如何加入MySQL中的兩個表(多對一)並獲得特定的JSON output(如下圖)

注意:請不要將其標記為重復

之前發布的一個問題與此非常相似,但在幾點上並不相同。

不是我要找的,這個問題與此不同: Mysql concat 和 group_concat

我在這篇文章的底部放了一個更長的描述和更多的細節,為什么應該將其標記為重復,以及它有何不同。


要求:

  1. 返回 JSON
  2. 使用:JSON_OBJECT & JSON_ARRAYAGG(不要使用 CONCAT 或 GROUP_CONCAT)
  3. 僅連接兩個表(通過主鍵/外鍵 | 行標識符) | 多對一關系
  4. 顯示在 output 中,來自父表的字段(不僅僅是 id 外鍵引用
  5. 在輸出 JSON 中,我需要控制每個元素或結構的名稱,它對應一個表名,但是 JSON 程式化會有所不同,並且還要控制每個字段的名稱(JSON 程式化名稱會與數據庫字段名)

output JSON 將是一個數組(teams),數組(struct)的每個元素都將包含一個數組(persons)。

頂級數組屬於父表“teams”(JSON 數組的每個元素包含單行數據),嵌套數組屬於子表“persons”,它與父表具有多對一關系。


如果一個簡單的 select 僅從一張表完成: select * from <child_table>;

我得到了父表的 id(主鍵),但是在 JSON 結果中,除了父主鍵,我還想顯示父表的另一個字段(父表中的字段值,而不僅僅是行 id / 鍵,這對 JSON 輸出沒有幫助)。


此處提供: .sql 文件以創建數據庫、架構、插入數據(以測試解決方案)

create schema if not exists test;

use test;
create table if not exists team
(
    id          int unsigned auto_increment primary key,
    team_name   varchar(30) unique not null,
    description text
);

use test;
create table if not exists person
(
    id          int unsigned auto_increment primary key,
    id_team     int unsigned not null,
    person_name varchar(40)  not null,
    notes       varchar(40)  not null,
    constraint team_person unique (id, id_team),
    foreign key (id_team) references team (id)
);

-- insert teams (2)
use test;
insert into team(team_name)
values ('team1');

insert into team(team_name)
values ('team2');

insert into team(team_name)
values ('team3');

-- insert persons (x2 per team = 4)
use test;
insert into person(id_team, person_name)
values ((select id from team where team_name = 'team1'),
        'john');

insert into person(id_team, person_name)
values ((select id from team where team_name = 'team1'),
        'tom');

insert into person(id_team, person_name)
values ((select id from team where team_name = 'team1'),
        'marie');

-- team 2
insert into person(id_team, person_name)
values ((select id from team where team_name = 'team2'),
        'scott');

insert into person(id_team, person_name)
values ((select id from team where team_name = 'team2'),
        'mark');

我需要 output JSON 看起來像這樣(完全展開 - 兩個 arrays 具有來自兩個表的值):

您在這里看到的是一組團隊,“團隊”表中每行一個 JSON 元素。

在每個元素中,一組人,每行一個 JSON 元素,來自“人”表,代表多對一關系。

{
  "team_persons": [
    {
      "team": "team1",
      "id_team": 1,
      "persons": [
        {
          "id_person": 1,
          "personaName": "john"
        },
        {
          "id_person": 2,
          "personaName": "allison"
        }
      ]
    },
    {
      "team": "team2",
      "id_team": 2,
      "persons": [
        {
          "id_person": 3,
          "personaName": "katrina"
        },
        {
          "id_person": 4,
          "personaName": "scott"
        }
      ]
    }
  ]
}

output中可以看到,JSON output中的每條記錄中都顯示了父表字段: id_team & team_name

JSON中有兩個arrays:

  1. 包含團隊列表或集合(父表)的頂級(結構)數組
  2. 在每個團隊中,都有屬於該團隊的人員列表或集合

我知道SELECT JSON_OBJECT / JSON_ARRAYAGG會涉及。 我不確定如何在兩個表的 SQL 連接中同時使用兩者,以實現所需的自定義 JSON output。

SQL 中的兩個表的連接如下所示:

select t.id id_team, p.id id_person, p.person_name, t.team_name
from team t,
     person p
where t.id = p.id_team;

謝謝你!


請不要將其標記為重復,它不是:

我只處理兩個表,其中 JSON output 需要從一個非常頂級的數組開始(與其他帖子不同)。

{
  "team_persons": [

引用的帖子和方法存在問題:

  1. 參考帖子中的示例沒有提供有關表和關系的足夠詳細信息,而且這是一個實際問題,沒有分解為最簡單的基本要素
  2. 最初的方法嘗試使用CONCAT / GRUOP_CONCAT ,我想避免使用

有一種更好、更現代的方法可以使用其他內置 MySQL 函數來執行此操作。

請不要關閉這個問題。 要求非常不同。

我需要一種使用的方法: JSON_OBJECT / JSON_ARRAYAGG and NOT CONCAT and NOT GROUP_CONCAT 並且也僅在兩個非常簡單的表上。

問問題時,如果試圖解決的最簡單(不准確)的事情能幫助其他人 map 他們的問題就成了問題。 在下面的問題中,我去除了所有復雜性以提供一個簡單示例。

我希望提供一個更容易理解的問題,其他人可能會從中受益(使用復制表結構的代碼),以及一個更精致的答案,因為我相信給出的答案對於更簡單的用例來說可以變得更簡單,並且更容易理解。

SELECT 
  JSON_PRETTY(
    JSON_OBJECT(
      'team_persons', JSON_ARRAYAGG(
        JSON_OBJECT(
          'team', team,
          'id_team', id_team,
          'persons', persons
        )
      )
    )
  ) AS _result
FROM (
  SELECT 
    t.id AS id_team,
    t.team_name AS team,
    JSON_ARRAYAGG(
      JSON_OBJECT(
        'id_person', p.id, 
        'personName', p.person_name
      )
    ) AS persons
  FROM team t JOIN person p ON t.id = p.id_team
  GROUP BY id_team
) AS p;

在 MySQL 8.0.28 上測試過,但它也應該適用於 MySQL 5.7.22(或更高版本)。


包括空隊是棘手的。 一開始只能使用 LEFT OUTER JOIN,但隨后它會抱怨,除非我將 GROUP BY 更改為引用基列,而不是別名:

  ...
  FROM team t LEFT OUTER JOIN person p ON t.id = p.id_team
  GROUP BY t.id

但是,這可能不會產生您想要的結果,我假設它是一個空的 JSON 數組。 因為外部聯接的結果確實有一行,但是帶有 NULL,所以您會得到一個帶有 NULL 的假團隊成員:

{
  "team": "team3",
  "id_team": 3,
  "persons": [
    {
      "id_person": null,
      "personName": null
    }
  ]
}

一種解決方法是將當前查詢與 JOIN 與另一個排除連接查詢聯合起來:

SELECT
  JSON_PRETTY(
    JSON_OBJECT(
      'team_persons', JSON_ARRAYAGG(
        JSON_OBJECT(
          'team', team,
          'id_team', id_team,
          'persons', persons
        )
      )
    )
  ) AS _result
FROM (
  SELECT 
    t.id AS id_team,
    t.team_name AS team,
    JSON_ARRAYAGG(
      JSON_OBJECT(
        'id_person', p.id,
        'personName', p.person_name
      )
    ) AS persons
  FROM team t JOIN person p ON t.id = p.id_team
  GROUP BY t.id
  UNION
  SELECT 
    t.id,
    t.team_name,
    JSON_ARRAY()
  FROM team t LEFT OUTER JOIN person p ON t.id = p.id_team
  WHERE p.id_team IS NULL
) AS p;

UNION 的后半部分返回一個文字空數組,因為反正團隊中沒有人。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM