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 个表并获取具有相同值的子行的主要内容,如果未能解决你的问题,请参考以下文章