【问题标题】:Selecting the latest record within a table选择表中的最新记录
【发布时间】:2021-05-16 16:53:29
【问题描述】:

我有一个 Oracle v11 数据库,虽然我没有表的架构定义,但我在下面说明了我想要实现的目标。

这就是表格的样子

我正在尝试通过仅选择最新行来转换数据,表格保留更改历史记录,我对更改不感兴趣,只对每个当前问题的最新值感兴趣

这是我目前所拥有的。

select issueno,
  case (when fieldname = 'name' then string_value end) name,
  case (when fieldname = 'point' then string_value end) point
from issues
where issueno = 1234

上面查询的问题是它返回4行,我想只返回一行。

【问题讨论】:

    标签: sql oracle oracle11g greatest-n-per-group


    【解决方案1】:

    您可以通过在MAX() KEEP (..) 值中为transition_date(或load_date 列,取决于您在查询中替换的意思)使用LAST ORDER BY 子句来获取最新日期作为

    WITH i AS
    (
    SELECT CASE WHEN fieldname = 'name' THEN
                 MAX(string_value) KEEP (DENSE_RANK LAST ORDER BY transition_date)
                                   OVER (PARTITION BY issue_no, fieldname) 
                 END AS name,
           CASE WHEN fieldname = 'point' THEN
                 MAX(string_value) KEEP (DENSE_RANK LAST ORDER BY transition_date)
                                   OVER (PARTITION BY issue_no, fieldname) 
                 END AS point                
      FROM issues 
    )
    SELECT MAX(name) AS name, MAX(point) AS point 
      FROM i
    

    但是,如果相关日期值出现 ties(equal values),则考虑使用 DENSE_RANK() 函数来计算返回等于 1ROW_NUMBER() 的值能够与主查询中的 JOIN 子句一起使用,例如

    WITH i AS
    (
    SELECT i.*,
           DENSE_RANK() OVER ( PARTITION BY issue_no, fieldname 
                                   ORDER BY transition_date DESC) AS dr,
           ROW_NUMBER() OVER ( PARTITION BY issue_no, fieldname 
                                   ORDER BY transition_date DESC) AS rn
      FROM issues i
    )
    SELECT i1.string_value AS name, i2.string_value AS point
      FROM ( SELECT string_value, rn FROM i WHERE dr = 1 AND fieldname = 'name'  ) i1
      FULL JOIN ( SELECT string_value, rn FROM i WHERE dr = 1 AND fieldname = 'point' ) i2
        ON i2.rn = i1.rn
    

    Demo

    【讨论】:

      【解决方案2】:

      假设您希望按列 load_date 获得最新记录

      select issueno,
        case (when fieldname = 'name' then string_value end) name,
        case (when fieldname = 'point' then string_value end) point
      from issues
      where issueno = 1234 and 
      (fieldname , load_date) in (select fieldname ,max(load_date) from issues where issueno=1234 group by fieldname)
      

      【讨论】:

        【解决方案3】:

        我会使用子查询 + 窗口函数来实现您的要求(假设您使用的是基于 load_date 来确定最新记录)

        select issueno,
          case (when fieldname = 'name' then string_value end) name,
          case (when fieldname = 'point' then string_value end) point
        from 
        (
        SELECT name, point, ROW_NUMBER() OVER(PARTITION BY ISSUENO, FIELDNAME ORDER BY LOAD_DATE DESC) RN 
        FROM issues
        )
        where issueno = 1234
        AND RN = 1
        

        语法ROW_NUMBER() OVER ([query_partition_clause] order_by_clause) 实际上是一个窗口函数,它为每一行分配一个排名,由您在[query_partition_clause] order_by_clause 中声明规则的方式控制

        【讨论】:

          【解决方案4】:

          看看这样的事情是否有帮助;在代码中读取 cmets。

          SQL> with issues (issueno, fieldname, string_value,
            2               transition_date, transition_id, load_date)
            3    as
            4    -- sample data; you have it in a table, don't type that
            5    (select 1234, 'name', null , date '2021-01-01', 1, date '2021-01-02' from dual union all
            6     select 1234, 'name', 'Tom', date '2021-02-11', 2, date '2021-02-12' from dual union all
            7     select 1234, 'point', '0' , date '2021-02-04', 3, date '2021-02-05' from dual union all
            8     select 1234, 'point', '5' , date '2021-02-10', 5, date '2021-02-11' from dual
            9    ),
           10  -- query you need begins here
           11  temp as
           12    -- rank values partitioned by ISSUENO and FIELDNAME, sorted by TRANSITION_ID
           13    (select issueno, fieldname, string_value,
           14       row_number() over (partition by issueno, fieldname
           15                          order by transition_id desc) rn
           16     from issues
           17    )
           18  select issueno,
           19    max(case when fieldname = 'name'  then string_value end) name,
           20    max(case when fieldname = 'point' then string_value end) point
           21  from temp
           22  where rn = 1
           23  group by issueno;
          
             ISSUENO NAME       POINT
          ---------- ---------- ----------
                1234 Tom        5
          
          SQL>
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-03-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-06-14
            • 2015-09-06
            相关资源
            最近更新 更多