Oracle 选择多条记录的最大日期
Posted
技术标签:
【中文标题】Oracle 选择多条记录的最大日期【英文标题】:Oracle Select Max Date on Multiple records 【发布时间】:2012-05-25 21:37:09 【问题描述】:我有以下 SELECT 语句,基于我在这里看到的:SQL Select Max Date with Multiple records 我的示例设置方式相同。我在 Oracle 11g 上。它不是为每个asset_tag 返回一条记录,而是返回多个记录。没有源表中的记录那么多,但(我认为)应该多。如果我运行内部 SELECT 语句,它还会返回正确的记录集(每个asset_tag 1 个),这真的让我很难过。
SELECT
outside.asset_tag,
outside.description,
outside.asset_type,
outside.asset_group,
outside.status_code,
outside.license_no,
outside.rentable_yn,
outside.manufacture_code,
outside.model,
outside.manufacture_vin,
outside.vehicle_yr,
outside.meter_id,
outside.mtr_uom,
outside.mtr_reading,
outside.last_read_date
FROM mp_vehicle_asset_profile outside
RIGHT OUTER JOIN
(
SELECT asset_tag, max(last_read_date) as last_read_date
FROM mp_vehicle_asset_profile
group by asset_tag
) inside
ON outside.last_read_date=inside.last_read_date
有什么建议吗?
【问题讨论】:
【参考方案1】:我认为您需要添加...
AND outside.asset_tag=inside.asset_tag
...符合ON
列表中的条件。
也不需要RIGHT OUTER JOIN
。 INNER JOIN
将给出相同的结果(并且可能更有效),因为在mp_vehicle_asset_profile
中不存在的子查询中不可能有asset_tag
和last_read_date
的组合。
即便如此,如果存在“关系”,查询可能会为每个资产标签返回多于一行——即具有相同last_read_date
的多行。相比之下,@Lamak 的基于分析的答案会在这种情况下任意选择一行。
您的评论表明您希望通过为last_read_date
选择具有最高mtr_reading
的行来打破平局。
您可以通过将OVER
子句中的ORDER BY
更改为:
ORDER BY last_read_date DESC, mtr_reading DESC
如果仍然存在平局(即多行具有相同的asset_tag
、last_read_date
和mtr_reading
),则查询将再次随意选择一行。
您可以修改我的基于聚合的答案以使用最高 mtr_reading
打破平局,如下所示:
SELECT
outside.asset_tag,
outside.description,
outside.asset_type,
outside.asset_group,
outside.status_code,
outside.license_no,
outside.rentable_yn,
outside.manufacture_code,
outside.model,
outside.manufacture_vin,
outside.vehicle_yr,
outside.meter_id,
outside.mtr_uom,
outside.mtr_reading,
outside.last_read_date
FROM
mp_vehicle_asset_profile outside
INNER JOIN
(
SELECT
asset_tag,
MAX(last_read_date) AS last_read_date,
MAX(mtr_reading) KEEP (DENSE_RANK FIRST ORDER BY last_read_date DESC) AS mtr_reading
FROM
mp_vehicle_asset_profile
GROUP BY
asset_tag
) inside
ON
outside.asset_tag = inside.asset_tag
AND
outside.last_read_date = inside.last_read_date
AND
outside.mtr_reading = inside.mtr_reading
如果仍然存在关联(即多行具有相同的asset_tag
、last_read_date
和mtr_reading
),则查询可能会再次返回多行。
基于分析和聚合的答案的另一个不同之处在于它们对空值的处理。如果 asset_tag
、last_read_date
或 mtr_reading
中的任何一个为 null,则基于分析的答案将返回相关行,但基于聚合的答案不会(因为连接中的相等条件不会评估为 @987654345 @ 当涉及到 null 时。
【讨论】:
这是我需要的。在一次修复中解决了它。我没有考虑其他汽车的最后阅读日期相同的多条记录,所以我没有想到要添加它。我认为 last_read_date 是一个 DATETIME 字段,但我错了。谢谢! 只是为了(希望)清楚...即使您将条件添加到ON
列表并按照我的建议使用和INNER JOIN
,查询仍可能返回不止一行如果last_read_date
上有“关系”,则为资产标签。如果这不是你想要的,如何打破关系? @Lamak 基于分析的答案将任意选择一个,或者可以修改(通过将表达式添加到 ORDER BY
列表)以其他方式打破联系。还有一些方法可以修改我的基于聚合的答案来做同样的事情。有兴趣可以回帖。
在这个数据集中,我并不太担心平局的情况,但让我们来探索一下。如果在日期出现平局,我想选择该日期存在的任何mtr_reading
中的最高值。推理是,正在驾驶的汽车可能在早上驾驶,然后在报告运行前的晚上再次驾驶。我们会在外部查询中添加一个order by ... mtr_reading
,从而对那些进行排序吗?还是我们需要调整内部查询?【参考方案2】:
尝试分析函数:
SELECT outside.asset_tag,
outside.description,
outside.asset_type,
outside.asset_group,
outside.status_code,
outside.license_no,
outside.rentable_yn,
outside.manufacture_code,
outside.model,
outside.manufacture_vin,
outside.vehicle_yr,
outside.meter_id,
outside.mtr_uom,
outside.mtr_reading,
outside.last_read_date
FROM ( SELECT *, ROW_NUMBER() OVER(PARTITION BY asset_tag ORDER BY last_read_date DESC) Corr
FROM mp_vehicle_asset_profile) outside
WHERE Corr = 1
【讨论】:
出于好奇,“Corr”代表什么? Corr 是行中项目的别名,所以行号返回一个数字,Lamak 给它起了一个别名,并用它来检索第 1 行。以上是关于Oracle 选择多条记录的最大日期的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Rails 中选择通过连接到另一个具有多条记录的表的最新记录