【问题标题】:Oracle query needs to return the highest date from resultOracle 查询需要从结果中返回最高日期
【发布时间】:2011-05-25 19:22:35
【问题描述】:

我有一个非常大的查询,这给我带来了一些麻烦,因为一个联接可以返回多行。我只想要此结果集中的最新行(由日期字段标识),但我似乎无法将正确的查询放在一起使其工作。

我需要 MAX 日期的查询是:

SELECT custid,reason,date FROM OPT opt WHERE opt.custid = 167043;

确实可以通过连接找到 Teh custid,但为简单起见,我已将其添加到此处的 where 子句中。此查询产生以下结果:

custid    grunn       date
167043  "Test 1"    19.10.2005 12:33:18
167043  "Test 2"    28.11.2005 16:23:35
167043  "Test 3"    14.06.2010 15:43:16

我怎样才能从这个结果集中只检索一条记录?那个记录是日期最高的记录?最终我把它放到一个做很多连接的大查询中,所以希望我可以把这个例子用在我更大的查询中。

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    具有 ROW_NUMBER 和 KEEP 的两种解决方案都很好。在检索大量列时,我倾向于使用 ROW_NUMBER,并为一两列保留 KEEP,否则您将不得不处理重复项,并且该语句将变得非常难以阅读。

    然而,对于少数列,KEEP 应该表现更好

    【讨论】:

    • 几年前你不是在你的博客上写过一些关于在多列中使用“keep”的东西吗?将其添加到您的答案中,我会投票赞成。
    【解决方案2】:

    而不是使用 row_number() 我认为最好选择您实际想要选择的内容(例如最后日期)

    SELECT custid
    ,      reason
    ,      date
    from
    (
        SELECT custid
        ,      reason
        ,      date
        ,      max(opt.date) over (partition by opt.custid order by opt.date) last_date 
        FROM   OPT opt 
        WHERE  opt.custid = 167043;
    )
    where  date = last_date
    

    【讨论】:

    • ...尽管如果日期不是唯一的,您会冒返回多行的风险
    【解决方案3】:

    或者以聚合形式使用LAST 函数的另一种方式。

    with my_source_data as (
      select 167043 as custid, 'Test 1' as reason, date '2010-10-01' as the_date from dual union  all
      select 167043 as custid, 'Test 2' as reason, date '2010-10-02' as the_date from dual union  all
      select 167043 as custid, 'Test 3' as reason, date '2010-10-03' as the_date from dual union  all
      select 167044 as custid, 'Test 1' as reason, date '2010-10-01' as the_date from dual
    )
        select 
          custid,
          max(reason) keep (dense_rank last order by the_date) as reason,
          max(the_date)
        from my_source_data
        group by custid
    

    我发现这非常有用,因为它将查找最后一行和值的过程合二为一。使用MAX(或其他聚合函数,例如MIN)以防分组和排序依据的组合不确定。

    这个函数基本上会根据分组取列的内容,按照给定的顺序排序,然后取最后一个值。

    【讨论】:

      【解决方案4】:

      你可以这样做:

      SELECT * FROM
      ( SELECT custid,reason,date FROM OPT opt WHERE opt.custid = 167043
        ORDER BY date DESC
      ) 
      WHERE ROWNUM = 1;
      

      【讨论】:

        【解决方案5】:

        您可以使用解析函数来解决它。试试这样的:

        select custid 
              ,reason
              ,date
          from (select custid 
                      ,reason
                      ,date
                      ,row_number() over(partition by cust_id order by date desc) as rn
                 from opt)
         where rn = 1;
        

        它是这样工作的:结果集被分成 cust_id (partition by) 组。在每个组中,行将按日期列降序排列 (order by)。组中的每一行都将分配一个从 1 到 N 的序列号 (row_number)。 这样,日期值最高的行将被分配 1,第二个最新的 2,第三个最新的 3 等等。

        最后,我只选择 nr = 1 的行,这基本上过滤掉了其他行。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-11-03
          • 2021-01-08
          • 1970-01-01
          • 1970-01-01
          • 2021-05-21
          • 1970-01-01
          • 2019-10-19
          • 2021-08-16
          相关资源
          最近更新 更多