MySQL选择具有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

以下表为例,将列出的查询作为基本查询,我想添加一种方法,仅选择具有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
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;