一对多取一条记录

烂柯 发布于 2023-08-15 84 次阅读


一、概述

​ 一对多关系,分表只取关联的第一条记录。最近遇到需要联表查询取最近的一条数据的需求(以前写过忘记了,为此记录下),首先我使用了Free SQL在官网上找到了此条经验内容,在此便基于此内容进行sql记录,以备后续所需(查询方名词案非专业名称😁😁😁)。

二、环境

基于mysql8.0,结构与fressl Issues#430相似,结构如下

CREATE TABLE `BaseType`  (
  `Id` int NOT NULL AUTO_INCREMENT,
  `TypeCode` varchar(100) NULL DEFAULT '',
  `SortCode` int NULL,
  `FullName` varchar(100) NULL DEFAULT '',
  PRIMARY KEY (`Id`)
);

CREATE TABLE `BaseItem`  (
  `Id` int NOT NULL AUTO_INCREMENT,
  `ItemName` varchar(100) NULL DEFAULT '',
  `BaseTypeId` int NULL,
  PRIMARY KEY (`Id`)
);

三、查询方案

1、联表子查询

SELECT a.*,b.*
FROM `BaseType` a
LEFT JOIN `BaseItem` b ON b.`id` = (SELECT b2.`id` FROM `BaseItem` b2 WHERE a.`id` = b2.`BaseTypeId` ORDER BY b2.Id DESC  LIMIT 1);

2、联表分组查询

SELECT a.*,b.*
FROM `BaseType` a
LEFT JOIN `BaseItem` b 
ON a.Id=b.BaseTypeId
RIGHT JOIN (SELECT BaseTypeId,MAX(Id) Id from `BaseItem` GROUP BY BaseTypeId) c
ON b.BaseTypeId=c.BaseTypeId AND b.Id=c.Id;

max(id)中id字段只是模拟排序字段,实际可能是创建时间等。左联是为补充数据,右联是为筛选数据。

四、总结

​ 不是很熟悉解释器,结论仅供参考实际使用请以实际场景数据测试。简单来看,子查询走索引,a表全表扫描1次。分组查询虽然全表扫描次数多,但是分组创建了临时表扫描的数据相对少。理论上数据少两种方式耗时差不多,主表数据较少外联表数据多分组查询会更快,主表数据较多外联表数据多子查询会更快。

烂柯