如何检索表的值以获取sql中两列的最大值

Posted

技术标签:

【中文标题】如何检索表的值以获取sql中两列的最大值【英文标题】:How to retrieve the values of the table for the max value of two columns in sql 【发布时间】:2019-06-18 21:15:42 【问题描述】:

我试图通过从两个不同的日期列中获取最大值来查询一个表,并输出两个日期都具有最大值的所有记录

该表有 6 列,包括 st_id(string)(有多个相同 id 的条目)、as_of_dt(int) 和 ld_dt_ts(timestamp)。从这个表中,我试图获取 as_of_dt 和 ld_dt_ts 的最大值,并按 st_id 分组并显示所有记录。

这很完美,但并不是最理想的

SELECT A.st_id, A.fl_vw, A.tr_record FROM db.tablename A 
INNER JOIN (
    SELECT st_id, max(as_of_dt) AS as_of_dt, max(ld_dt_ts) AS ld_dt_ts 
    From db.tablename 
    group by st_id
) B on A.st_id = B.st_id and A.as_of_dt = B.as_of_dt and A.ld_dt_ts= B.ld_dt_ts

--

预期结果应返回具有 as_of_dt 和 ld_dt_ts 最大值的 st_id,即,这将是每个 st_id 的最新记录。

【问题讨论】:

meta.***.com/questions/333952/… 此外,关于查询性能的问题总是需要给定查询的 EXPLAIN 这是经典的查表任务,提供的sql是使用join的,效率不如解析函数,因为需要两次表扫描和一次join。我认为这个问题不应该结束。 【参考方案1】:

使用解析rank()函数。 rank() 会将1 分配给st_id 分区中具有最大日期的所有记录:

SELECT s.st_id, s.fl_vw, s.tr_record
from
(
SELECT A.st_id, A.fl_vw, A.tr_record,
       rank() over(partition by st_id order by as_of_dt desc) rnk_as_of_dt,
       rank() over(partition by st_id order by ld_dt_ts desc) rnk_ld_dt_tsrnk
  FROM db.tablename A 
)s 
WHERE rnk_as_of_dt=1 ANDrnk=1 rnk_ld_dt_ts=1 --get records with max dates in both columns

两个等级可以这样组合:

SELECT s.st_id, s.fl_vw, s.tr_record
from
(
SELECT A.st_id, A.fl_vw, A.tr_record,
       rank() over(partition by st_id order by as_of_dt desc, ld_dt_ts desc) rnk
  FROM db.tablename A 
)s 
WHERE rnk=1  --get records with max dates combination 

但这与您的原始查询并不完全相同。 例如,如果你有这个数据集:

st_id, as_of_dt, ld_dt_ts 
1       1         2
1       2         1

然后这个查询

SELECT st_id, max(as_of_dt) AS as_of_dt, max(ld_dt_ts) AS ld_dt_ts 
    From db.tablename 
    group by st_id

将返回:

st_id, as_of_dt, ld_dt_ts 
1       2         2

而final join 不会返回任何行,因为不存在这样组合的任何行,而两个rank 组合的查询将返回:

st_id, as_of_dt, ld_dt_ts 
1       2         1

如果您的数据中不存在这样的数据集(例如,ld_dt_ts 始终>=as_of_dt),那么您可以将排名合并为一个,甚至只使用一个按顺序排列的日期。

【讨论】:

非常感谢,这真的很好,很好的优化,我正在尝试类似的方法。将其发布在答案中。【参考方案2】:

--我正在使用row_number()函数,--

row_number() over(PARTITION BY st_id ORDER BY as_of_dt DESC, ld_dt_ts DESC) RN 来自 db.tablename s)tmp where RN=1

【讨论】:

这与您在问题中的原始查询不完全相同。你说问题中的查询完美无缺。看:只有一行会被标记为 RN=1,如果你有超过 1 行的最大日期,它们将不会被返回。 如果您想要与使用连接的初始查询完全相同的行为,则需要排名。是的,排名可以合并为一个排名,我编辑了答案。但这又取决于数据。如果您有 st_id=1, dt1=1, dt2=2 和 st_id=1, dt1=2, dt2=1 那么您的最大子查询(在问题中)将返回: st_id=1, dt1=2, dt2=2 和final join 将不返回任何行。 rank 组合查询将返回 st_id=1、dt1=2、dt2=1 的 1 行。因此,结合两个等级可能会产生不同的效果 如果我们对您的数据集应用一些限制,例如,对于相同的 ID,只能存在具有最大日期的一行,并且可能还有一个限制:ld_dt_ts always>=as_of_dt 那么您的 row_number 可以完全按照与初始查询相同。并且具有两个等级的查询会重现您的原始查询行为,而对数据集没有任何限制

以上是关于如何检索表的值以获取sql中两列的最大值的主要内容,如果未能解决你的问题,请参考以下文章

如何从外键表中检索值?

下载sql表的值以供离线重用

SQL 更新一个表中的值以匹配 Oracle SQL Developer 中另一个表的值

sql 怎样查1列多值全都在一个集合里面

比较来自两个不同表的两列的逗号分隔值

在 SQL Server 中检索 VARCHAR 列的最大长度