MySQL选择具有max id的行并匹配其他条件
以下表为例,将列出的查询作为基本查询,我想添加一种方法,仅选择具有max id的行!无需进行第二次查询MySQL选择具有max id的行并匹配其他条件,mysql,max,Mysql,Max,以下表为例,将列出的查询作为基本查询,我想添加一种方法,仅选择具有max id的行!无需进行第二次查询 TABLE VEHICLES id vehicleName ----- -------- 1 cool car 2 cool car 3 cool bus 4 cool bus 5 cool bus 6 car 7 truck 8 motorcycle 9 scooter
TABLE VEHICLES
id vehicleName
----- --------
1 cool car
2 cool car
3 cool bus
4 cool bus
5 cool bus
6 car
7 truck
8 motorcycle
9 scooter
10 scooter
11 bus
TABLE VEHICLE NAMES
nameId vehicleName
------ -------
1 cool car
2 cool bus
3 car
4 truck
5 motorcycle
6 scooter
7 bus
TABLE VEHICLE ATTRIBUTES
nameId attribute
------ ---------
1 FAST
1 SMALL
1 SHINY
2 BIG
2 SLOW
3 EXPENSIVE
4 SHINY
5 FAST
5 SMALL
6 SHINY
6 SMALL
7 SMALL
和基本查询:
select a.*
from vehicle a
join vehicle_names b using(vehicleName)
join vehicle_attribs c using(nameId)
where c.attribute in('SMALL', 'SHINY')
and a.vehicleName like '%coo%'
group
by a.id
having count(distinct c.attribute) = 2;
因此,我想要实现的是选择具有特定属性的行,这些属性匹配一个名称,但每个名称只有一个条目匹配id最高的位置
因此,本例中的工作解决方案将返回以下行:
id vehicleName
----- --------
2 cool car
10 scooter
如果它在id上使用了某种max
目前,我得到了所有酷车和滑板车的参赛作品
我的真实世界数据库遵循类似的结构,其中有10个成千上万的条目,因此像上面这样的查询可以轻松返回3000多个结果。我将结果限制为100行,以保持执行时间较低,因为结果用于我的站点上的搜索。我重复使用相同名称但ID不同的“车辆”的原因是不断添加新车型,但我保留了旧车型以供那些想要挖掘它们的人使用!但是在按车名搜索时,我不想返回旧卡,只想返回ID最高的最新卡
正确的答案将修改我在上面提供的查询,我目前正在使用它,并且它只返回名称匹配但id最高的行
如果这是不可能的,建议我如何实现我想要的,而不大幅增加搜索的执行时间将不胜感激 该表似乎没有标准化,但这有助于您做到这一点:
select max(id), vehicleName
from VEHICLES
group by vehicleName
having count(*)>=2;
我不确定我是否完全理解您的模型,但下面的查询满足您目前的需求。第一个子查询查找车辆的最新版本。第二个查询满足“and”条件。然后我加入对vehiclename的查询(哪个是关键?) 如果这个“最新车辆”逻辑是您需要经常做的事情,那么一个小建议是创建一个视图(见下文),该视图返回每个车辆的最新版本。然后可以使用视图而不是find max查询。请注意,这纯粹是为了易于使用,它不提供性能优势
select *
from vehicle a
where id = (select max(b.id)
from vehicle b
where a.vehiclename = b.vehiclename);
如果不对模型进行适当的重新设计,您可能会 1) 添加应用程序可以管理的列IsLatest 这并不完美,但可以满足您的问题(在下一个问题之前,请参见结尾处的not) 您所需要的只是添加一个新条目以发出查询,例如
UPDATE a
SET IsLatest = 0
WHERE IsLatest = 1
INSERT new a
UPDATE a
SET IsLatest = 1
WHERE nameId = @last_inserted_id
在事务或触发器中
2) 或者,您可以在发出查询之前找到max_id
SELECT MAX(nameId)
FROM a
WHERE vehicleName = @name
3) 您可以在单个SQL中实现这一点,并在(vehicleName、nameId)上提供索引,它实际上应该具有相当快的速度
select a.*
from vehicle a
join vehicle_names b ON a.vehicleName = b.vehicleName
join vehicle_attribs c ON b.nameId = c.nameId AND c.attribute = 'SMALL'
join vehicle_attribs d ON b.nameId = c.nameId AND d.attribute = 'SHINY'
join vehicle notmax ON a.vehicleName = b.vehicleName AND a.nameid < notmax.nameid
where a.vehicleName like '%coo%'
AND notmax.id IS NULL
选择一个*
来自车辆a
将车辆名称b连接到a.vehicleName=b.vehicleName上
在b.nameId=c.nameId和c.attribute='SMALL'上加入车辆属性c
在b.nameId=c.nameId和d.attribute='shinny'上加入车辆属性d
在a.vehicleName=b.vehicleName和a.nameid
我已通过和删除了您的组,并将其替换为另一个联接(假设每个nameId只能有一个属性)
我还使用了一种方法来查找每个组的最大值,那就是连接一个表本身并过滤掉一行,该行中没有相同名称的id更大的记录
还有其他方法,搜索“每个组的最大sql”。另请参见,虽然不完整。如果您想保留您的逻辑,请看下面我将做什么:
select a.*
from vehicle a
left join vehicle a2 on (a.vehicleName = a2.vehicleName and a.id < a2.id)
join vehicle_names b on (a.vehicleName = b.vehicleName)
join vehicle_attribs c using(nameId)
where c.attribute in('SMALL', 'SHINY')
and a.vehicleName like '%coo%'
and a2.id is null
group by a.id
having count(distinct c.attribute) = 2;
这导致了以下查询:
select a.id, b.vehicleName
from vehicle a
left join vehicle a2 on (a.nameId = a2.nameId and a.id < a2.id)
join vehicle_names b on (a.nameId = b.nameId)
join vehicle_attribs c on (a.nameId=c.nameId)
inner join attribs d using (attribId)
where d.attribute in ('SMALL', 'SHINY')
and b.vehicleName like '%coo%'
and a2.id is null
group by a.id
having count(distinct d.attribute) = 2;
选择a.id、b.vehicleName
来自车辆a
左连接车辆a2 on(a.nameId=a2.nameId和a.id 具有计数(不同的d属性)=2代码>表格只是一个与实际情况完全不同的示例!小组对max重要吗?但我在回答中真正想要的是,我将向上面提供的查询中添加什么,以仅选择最大行数!谢谢您在(名称ID,属性)
上有车辆属性的索引吗?并使用搜索车辆名称,如“%cool%”
未使用任何index@ajreal车辆属性中有一个主键(nameId,attribs)。视图没有索引,因此,它可能不会以OP拥有的记录数量来加速查询结果。@Danosaure:我将编辑我的答案,使其更清楚地表明我的建议是为了提高易用性。当您需要每个组中的一条记录时,这是一种很好的排名方式,我没有想到这一点。我建议使用变量的解决方案,但是这个更好,因为查询的结果可能会缓存在查询缓存中。
+----+-------------+
| id | vehicleName |
+----+-------------+
| 2 | cool car |
| 10 | scooter |
+----+-------------+
2 rows in set (0.00 sec)
update vehicle a
inner join vehicle_names b using (vehicleName)
set a.vehicleName = b.nameId;
alter table vehicle change column vehicleName nameId int;
create table attribs (
attribId int auto_increment primary key,
attribute varchar(20),
unique key attribute (attribute)
);
insert into attribs (attribute)
select distinct attribute from vehicle_attribs;
update vehicle_attribs a
inner join attribs b using (attribute)
set a.attribute=b.attribId;
alter table vehicle_attribs change column attribute attribId int;
select a.id, b.vehicleName
from vehicle a
left join vehicle a2 on (a.nameId = a2.nameId and a.id < a2.id)
join vehicle_names b on (a.nameId = b.nameId)
join vehicle_attribs c on (a.nameId=c.nameId)
inner join attribs d using (attribId)
where d.attribute in ('SMALL', 'SHINY')
and b.vehicleName like '%coo%'
and a2.id is null
group by a.id
having count(distinct d.attribute) = 2;