MySql JOIN 3 个表并获取具有相同值的子行

Posted

技术标签:

【中文标题】MySql JOIN 3 个表并获取具有相同值的子行【英文标题】:MySql JOIN 3 tables and get child rows with same values 【发布时间】:2022-01-18 22:21:53 【问题描述】:

我有 3 个表:订单、项目和渲染。

1 个订单可以有多个项目,每个项目都有一个带有状态的渲染条目。

我想要订单 ID 和日期,其中所有项目都呈现为“完成”。

在示例中,仅订单 1,其 2 项(1 和 2)的状态在渲染表中完成

订单表

id| date
1 | 2021-12-10
2 | 2021-12-11

项目表

id|order_id
1 | 1
2 | 1
3 | 2
4 | 2

渲染表格

id|item_id| status
1 |1      | done
2 |2      | done
3 |3      | done
4 |4      | running

我希望它与 JOIN 语句一起使用。我已经尝试过了,但它不像预期的那样工作(它返回两个,订单 1 和 2):

SELECT o.id, o.date
FROM order AS o
JOIN item AS i ON o.id = i.order_id
JOIN render r1 ON (i.`id` = r1.item_id AND r1.status = 'done')
LEFT JOIN render r2 ON (i.`id` = r2.item_id AND r2.status <> 'done')
AND r2.item_id IS NULL;

有什么想法吗?提前谢谢你!

【问题讨论】:

【参考方案1】:
SELECT t1.id
     , t1.date
  FROM order
       t1
 WHERE t1.id NOT IN
       (
         SELECT o.id
           FROM order
                o
           JOIN item
                i
             ON i.order_id = o.id
           JOIN render
                r
             ON r.item_id = i.id
          WHERE r.status <> 'done'
       )

某些列名的选择是不幸的,这使得维护人员难以阅读连接条件:一目了然,id 列所指的 ID 是什么类型并不是很明显。

我将重命名以下列:

TABLE  COLUMN_NAME BETTER_COLUMN_NAME
------ ----------- ------------------
order  id          order_id
order  date        order_date
item   id          item_id
render id          render_id
render status      render_status

我也不同意 o / i / r 表别名,但争论在 12A 房间,就在走廊旁边。

【讨论】:

嘿,谢谢!您的解决方案运行良好。关于您提出的命名,我实际上编造了名称并简化了表格,以提高清晰度并降低复杂性。检查您的解决方案后,我想出了一个不使用子查询的解决方案。我也发在这里了【参考方案2】:

在这里我发布它最终对我最有效的内容,以防它帮助任何人:)

SELECT o.id, o.date
FROM order AS o
JOIN item AS i ON o.id = i.order_id
LEFT JOIN render r ON (r.item_id = i.id)
GROUP BY o.id
HAVING GROUP_CONCAT(DISTINCT IFNULL(r.status, "NULL")) = 'done';  

在 HAVING 子句中,我连接状态,删除所有重复项并检查是否只有“完成”。由于我需要针对渲染进行 LEFT JOIN,因此我将返回的空行显式设置为“NULL”。

【讨论】:

有了这个 GROUP_CONCAT 技巧,如果render 表变大,查询优化器就没有机会得出一个有效的执行计划,即使你索引了status 列。此外,阅读此查询的每个人都需要停下来了解它实际想要实现的目标。这种聪明的做法在 SQL 上下文中几乎不是一个好主意。

以上是关于MySql JOIN 3 个表并获取具有相同值的子行的主要内容,如果未能解决你的问题,请参考以下文章

mysql加入3个表并计数

MySQL LEFT JOIN 在第二个表中具有可选值

比较 2 个表并返回 MySQL 中的变化

SQL - 连接 2 个表并返回 2 行之间的值差异

加入 2 个表并在 codeigniter 中对条件求和

MS Access Inner Join 3 个具有相同 field_name 的表