在 WHERE IN 子句 SQL 中显示每条记录的 MAX 日期
Posted
技术标签:
【中文标题】在 WHERE IN 子句 SQL 中显示每条记录的 MAX 日期【英文标题】:Display the MAX date for each record in a WHERE IN clause SQL 【发布时间】:2019-11-09 12:33:00 【问题描述】:使用 mysql,我有一个名为subscriptions
的表,如下所示
name, renewal_date, national_id
---------------------------------------
ted, 1/2/2010, A1111R
ben, 1/3/2010, A145E1
bob, 8/4/2009, A11C11
kate, 2/2/2010, A111E1
ted, 12/2/2011, A1111R
bob, 12/2/2014, A11C11
ben, 12/2/2016, A145E1
etc..
该表有大约 150000 条记录。每个人可以有多个订阅。我想为给我查询的列表中的每条记录显示最大/最新renewal_date
。这是我的sql语句:
select d.name, d.renewal_date, d.national_id
from subscriptions d
where renewal_date= (select max(d1.renewal_date)
from subscriptions d1
where d1.national_id = d.national_id IN ('A1111R','A11C11', 'A145E1' ....));
当我在 phpmyadmin 中运行查询时,它似乎并没有结束执行,即使 IN
子句中的记录很少。
最好的方法是什么?我还应该说我还不是 SQL 专家 :-) 在此先感谢
【问题讨论】:
对于 MySQL,最好知道您正在使用的版本。最近发生了重要的变化。在 MySQL 8 中,有些事情比以前的版本更容易实现。 表中的同名可以有两个不同的national_id吗?如果是这样,您是想要姓名一个结果行还是每个姓名和national_id 一个结果行? 谢谢@ThorstenKettner。 MySQL 版本是 5.7.25。不,表中的同名不能有两个不同的national_id。 那么是时候修复数据库设计了。一张供有国民身份证的人使用,一张供订阅者使用。 【参考方案1】:假设给定人的姓名和国家 ID 不变,您可以只使用聚合:
select d.name, max(d.renewal_date), d.national_id
from subscriptions d
where d.national_id in ( . . . )
group by d.name, d.national_id;
如果您想要行上的所有列,最有效的方法通常是具有正确索引的相关子查询:
select s.*
from subscriptions s
where s.national_id in ( . . . ) and
s.renewal_date = (select max(s2.renewal_date)
from subscriptions s2
where s2.national_id = s.nation_id
);
正确的索引是(national_id, renewal_date)
。实际上,在许多情况下,这可能比 group by
查询更快。
【讨论】:
非常感谢@gordon-linoff 的出色回答和快速响应。第二个例子对我有用。最后,如果我想删除我显示的那些续订日期,我将如何从select
转换为delete
? delete s.renewal_date from...
之类的东西?
@adamvanbart:要删除这些行,只需将 select s.*
更改为 delete
。还是您想更新行并只删除(即设为 null)它们的日期?
谢谢@gordonlinoff。我不想删除整行,只删除renewal_date
然后把select s.* from subscriptions s
改成update subscriptions s set renewal_date = null
。
谢谢@ThorstenKettner。但是 MySQL 会抛出一个错误:#1093 - You can't specify target table 's' for update in FROM clause
【参考方案2】:
您需要每个名称的最大续订日期。如果是这样,那么您需要做的就是聚合:
select name, max(renewal_date)
from subscriptions
group by name
order by name;
我不知道,national_id 是如何进入 Play 的。一个人的national_id 真的可以从一个订阅更改为另一个订阅吗?还是您的数据库设计存在缺陷?
你可能想要这个:
select name, national_id, max(renewal_date)
from subscriptions
group by name, national_id
order by name, national_id;
或者这个:
select name, max(renewal_date), any_value(national_id)
from subscriptions
group by name
order by name;
或者这个:
select *
from subscriptions
where (name, renewal_date) in
(
select name, max(renewal_date)
from subscriptions
group by name
)
order by name;
【讨论】:
以上是关于在 WHERE IN 子句 SQL 中显示每条记录的 MAX 日期的主要内容,如果未能解决你的问题,请参考以下文章
是否可以使用“WHERE”子句来选择 SQL 语句中的所有记录?