如何检索表的值以获取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中两列的最大值的主要内容,如果未能解决你的问题,请参考以下文章