【问题标题】:Oracle Select Max Date on Multiple recordsOracle 选择多条记录的最大日期
【发布时间】: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

有什么建议吗?

【问题讨论】:

    标签: sql oracle select subquery max


    【解决方案1】:

    我认为您需要添加...

    AND outside.asset_tag=inside.asset_tag
    

    ...符合ON 列表中的条件。

    也不需要RIGHT OUTER JOININNER JOIN 将给出相同的结果(并且可能更有效),因为在mp_vehicle_asset_profile 中不存在的子查询中不可能有asset_taglast_read_date 的组合。

    即便如此,如果存在“关系”,查询可能会为每个资产标签返回多于一行——即具有相同last_read_date 的多行。相比之下,@Lamak 的基于分析的答案会在这种情况下任意选择一行。

    您的评论表明您希望通过为last_read_date 选择具有最高mtr_reading 的行来打破平局。

    您可以通过将OVER 子句中的ORDER BY 更改为:

    ORDER BY last_read_date DESC, mtr_reading DESC
    

    如果仍然存在平局(即多行具有相同的asset_taglast_read_datemtr_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_taglast_read_datemtr_reading),则查询可能会再次返回多行。

    基于分析和聚合的答案的另一个不同之处在于它们对空值的处理。如果 asset_taglast_read_datemtr_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 行。
    猜你喜欢
    • 2011-06-16
    • 1970-01-01
    • 1970-01-01
    • 2020-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多