【问题标题】:SQL JOIN two JSON columns, by two related idsSQL JOIN 两个 JSON 列,由两个相关的 id
【发布时间】:2022-06-19 21:51:06
【问题描述】:

我有两个相关的 JSON 列引用了多个表。

我需要匹配每个结果排列。

采取:

writers

| id | name | supervising (JSON)  | projects (JSON)   |
|:-- |:-----| :-------------------| :-----------------|
| 1  | John | ["3","4","5","6"]   | null              |
| 2  | Bill | ["7","8","9","10"]  | null              |
| 3  | Andy | null                | ["1","2"]         |
| 4  | Hank | null                | ["3","4","5"]     |
| 5  | Alex | null                | ["6","7","8"]     |
| 6  | Joe  | null                | ["9","10"]        |
| 7  | Ken  | null                | ["11","12","13"]  |
| 8  | Zach | null                | ["14","15","16"]  |
| 9  | Walt | null                | ["17","18"]       |
| 10 | Mike | null                | ["19","20","21"]  |
  • writers.supervising 是一个 JSON 对象,引用 writers.id
    • 约翰监督安迪、汉克、亚历克斯和乔
    • Bill 监督 Ken、Zach、Walt 和 Mike
  • writers.projects 是一个 JSON 对象,引用 projects.id
    • 安迪负责波士顿和芝加哥
    • 汉克负责思科、西雅图和北区
    • 等等

...约翰和比尔不写;他们监督writers.idwriters.supervising JSON 中列出的作者。

writerspapers 他们写...

projects

| id | title    |
|:-- |:---------|
| 1  | Boston   |
| 2  | Chicago  |
| 3  | Cisco    |
| 4  | Seattle  |
| 5  | North    |
| 6  | West     |
| 7  | Miami    |
| 8  | York     |
| 9  | Tainan   |
| 10 | Seoul    |
| 11 | South    |
| 12 | Tokyo    |
| 13 | Carlisle |
| 14 | Fugging  |
| 15 | Turkey   |
| 16 | Paris    |
| 17 | Midguard |
| 18 | Fugging  |
| 19 | Madrid   |
| 20 | Salvador |
| 21 | Everett  |

我需要与主管和论文一起工作:

  1. 获取 John 监督下作者的所有 projects.id 列表。
  2. 检查是否:
  • John (writers.id=1) 正在监督“Carlisle”(projects.id=13) 项目(0 行)
  • Bill (writers.id=2) 正在监督“Carlisle”(projects.id=13) 项目(1 行)

我需要什么:

我需要类似...

  1. 获取 John 监督下的作者的所有 projects.id 列表 (writers.id=1)。
SELECT p.id, p.title FROM projects p
JOIN writers w
WHERE JSON_CONTAINS(writer s ON s.supervising
  JSON_CONTAINS(w.projects)
)
AND s.id = '1';

想要的结果:

| 1  | Boston   |
| 2  | Chicago  |
| 3  | Cisco    |
| 4  | Seattle  |
| 5  | North    |
| 6  | West     |
| 7  | Miami    |
| 8  | York     |
| 9  | Tainan   |
| 10 | Seoul    |
  1. 检查 John (id1) 是否监督 Carlisle (id13)
SELECT id FROM projects p
WHERE writer s JSON_CONTAINS(writer w ON s.supervising
  JSON_CONTAINS("13" ON p.id)
)
AND s.id = '1';

想要的结果:0 rows

我认为两者都不对。但是,我知道我正在查看两个 JSON 对象的排列。

【问题讨论】:

标签: sql json database join mariadb


【解决方案1】:

当我理解你的问题正确时,结果应该是:

supervisor writer project p_id
John Andy Boston 1
John Andy Chicago 2
John Hank Cisco 3
John Alex Miami 7
John Hank North 5
John Hank Seattle 4
John Joe Seoul 10
John Joe Tainan 9
John Alex West 6
John Alex York 8
WITH RECURSIVE cte AS (
   SELECT 0 AS x
   UNION ALL
   SELECT x+1 FROM cte ),
tbl_writers AS (
SELECT
   id,
   name,
   -- cte.x,
   JSON_VALUE(projects,CONCAT('$[',cte.x,']')) AS project
FROM writers
CROSS JOIN cte
WHERE JSON_VALUE(projects,CONCAT('$[',cte.x,']')) IS NOT NULL
),
tbl_supervisors AS (
SELECT
   id,
   name,
   -- cte.x,
   JSON_VALUE(supervising,CONCAT('$[',cte.x,']')) AS writer
FROM writers
CROSS JOIN cte
WHERE JSON_VALUE(supervising,CONCAT('$[',cte.x,']')) IS NOT NULL
)
-- SELECT * FROM tbl_supervisors;
-- SELECT * FROM tbl_writers;
SELECT
   s.name  AS supervisor,
   w.name  AS writer,
   p.title AS project,
   p.id    AS p_id
FROM tbl_supervisors s
LEFT JOIN tbl_writers w ON w.id = s.writer
INNER JOIN projects p ON p.id = w.project
-- WHERE s.name = 'Bill' -- For Bill by name
-- WHERE s.id = '2'      -- For Bill by id
-- WHERE s.name = 'John' -- For John by name
WHERE s.id = '1'         -- For John by id
ORDER BY project;        -- By project alphabetical
-- ORDER BY p_id;        -- Example ORDER BY option from out AS col

见:db<>fiddle

使用common table expressions (CTE) 我首先创建两个表,(tbl_writers) 和 (tbl_supervisors)。 SQL 在表上比在 JSON 格式的数据上更有效,因为 SQL 诞生时还没有任何 JSON。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-22
    • 2020-10-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多