【问题标题】:Querying latest date for a particluar attribute where it is not in date format查询不是日期格式的特定属性的最新日期
【发布时间】:2016-11-02 15:04:41
【问题描述】:

我需要设置一个查询,允许我选择组中最近更新的记录。如果两条记录有最新更新,则应选择更新历史最长的一条。如果两者都为空,或者两者具有相同的历史长度,则不应选择两者。这些字段是 varchar2 格式。第一条记录和最后一条记录的最后两位数字对应于这些记录的年份。历史长度中的字母对应于获取的数据类型的代码。下面是一个示例表,具有预期的结果:

| group_id  |    id |   First Record  |  Last Record    |     History Length    |
---------------------------------------------------------------------------------
|   a       |    1  |  record98       |    record16     | SNDAWEDSPSEDSYSEAOE   |
|   a       |    2  |  record97       |    record14     | AVNDAWEDSPSEDSYS      |
|   b       |    3  |  record96       |    record15     | BVNDAWEDSPSEDSYSEAOE  |
|   b       |    4  |  record98       |    record16     | UNDAWEDSPSEDSYSEAOP   |
|   b       |    5  |  record95       |    record16     | UNDAWEDSPSEDSYSEAOPHYE|
|   c       |    6  |  record96       |    record12     | BVNDAWEDSPSEDSYSE     |
|   c       |    7  |  record10       |   record15      | HUSIKD                |
|   d       |    8  |    null         |      null       |            null       |
|   d       |    9  |    null         |      null       |            null       |
|   e       |   10  |  record11       |  record16       |    ASIKSO             |
|   e       |   11  |  record11       |  record16       |    SIXLLO             |
-------------------------------------------------------------------------------------------------------------------

输出

| group_id  |    id |   First Record  |  Last Record    |     History Length    |
---------------------------------------------------------------------------------
|   a       |    1  |  record98       |    record16     | SNDAWEDSPSEDSYSEAOE   |
|   b       |    5  |  record95       |    record16     | UNDAWEDSPSEDSYSEAOPHYE|
|   c       |    7  |  record10       |   record15      | HUSIKD                |

历史不如最新记录重要,所以如果太难实现,我只需要最新记录的那一行。谢谢。

【问题讨论】:

    标签: sql database oracle


    【解决方案1】:

    如果以下查询满足您的要求,请告诉我。

    SELECT group_id,ID,first_record,last_record,history_length
    FROM (
          SELECT group_id,ID,first_record,last_record,history_length,diff,
                 MAX(LENGTH(history_length)) OVER (PARTITION BY group_id) max_len,
                 count(1) OVER (PARTITION BY group_id,LENGTH(history_length)) cnt
          FROM (
               SELECT  group_id,ID,first_record,last_record,history_length,
                       count(1) OVER (PARTITION BY group_id,LENGTH(history_length)) cnt,
                       MAX(to_date(to_number(substr(last_record, 7,2)),'RR')-to_date(to_number(substr(first_record, 7,2)),'RR'))   OVER (PARTITION BY group_id) diff
               FROM (
                     SELECT group_id,ID,first_record,last_record,history_length,
                            MAX(last_record) OVER (PARTITION BY group_id) max_last_record
                     FROM  t
                     WHERE nvl(first_record,last_record) IS NOT NULL
                     )
                     WHERE last_record=max_last_record
               )
               WHERE   (to_date(to_number(substr(last_record, 7,2)),'RR')-to_date(to_number(substr(first_record, 7,2)),'RR'))=diff
          )
    WHERE cnt=1
    AND   LENGTH(history_length)=max_len;
    

    【讨论】:

    • 我收到“无效号码”错误。我正在使用 Toad,它突出显示 'REPLACE(last_record,'record')-' 中的 REPLACE;这些字段是 varchar;有没有办法将它们转换为日期,然后以此为基础进行查询?
    • 试试这个从列中获取数字。 REGEXP_REPLACE(last_record,'[[:alpha:]]')
    • 我试过 (REPLACE(to_number(substr(lastrecord, 7,2)))。它似乎有效。与此和您的建议有什么不同吗?
    • 如果 lastrecord 包含第 7 位和第 8 位的数字,那么您的技巧也将奏效。
    • 在大多数情况下,这行得通;但是我遇到了一个问题。一项记录来自 98-16,而另一记录来自 10-16。在这种情况下,我们想要 98-16 的记录(因为它更长),但它选择了较短的记录。关于如何解决的任何想法?
    【解决方案2】:

    我个人觉得 hemalp108 的回答很难理解;我更喜欢分解每一步。

    以下是我如何使用 CTE 进行此操作的,其中每个后续 CTE 都是具有描述性名称的下一步,即

    • 添加最大上次记录
    • 然后按 Max LastRecord 搜索
    • 然后添加 HistoryTally
    • 然后添加 Max HistoryTally
    • 然后按 Max HistoryTally 搜索
    • 然后添加 HistoryTally 频率
    • 然后按 HistoryTally 频率搜索
    • 然后返回结果

    附: SQLFiddle 不工作,所以我不得不在本地 SQL Server 中这样做(没有本地 Oracle)并尝试将其翻译回来!

    WITH YourTable AS 
    ( SELECT * 
        FROM ( VALUES ( 'a',1,'record98','record16','SNDAWEDSPSEDSYSEAOE' ),
                      ( 'a',2,'record97','record14','AVNDAWEDSPSEDSYS' ),
                      ( 'b',3,'record96','record15','BVNDAWEDSPSEDSYSEAOE' ),
                      ( 'b',4,'record98','record16','UNDAWEDSPSEDSYSEAOP' ),
                      ( 'b',5,'record95','record16','UNDAWEDSPSEDSYSEAOPHYE' ),
                      ( 'c',6,'record96','record12','BVNDAWEDSPSEDSYSE' ),
                      ( 'c',7,'record10','record15','HUSIKD' ),
                      ( 'd',8,null,null,null),
                      ( 'd',9,null,null,null),
                      ( 'e',10,'record11','record16','ASIKSO' ),
                      ( 'e',11,'record11','record16','SIXLLO' )
    ) AS T ( group_id, id, FirstRecord, LastRecord, HistoryLength ) ),
    
    AddMaxLastRecord AS
    ( SELECT *, MAX( LastRecord ) OVER ( PARTITION BY group_id ) MaxLastRecord
         FROM YourTable ),
    
    SearchByMaxLastRecord AS
    ( SELECT group_id, id, FirstRecord, LastRecord, HistoryLength
         FROM AddMaxLastRecord
       WHERE LastRecord = MaxLastRecord ),
    
    AddHistoryTally AS
    ( SELECT *, LEN( HistoryLength ) AS HistoryTally
         FROM SearchByMaxLastRecord ),
    
    AddMaxHistoryTally AS
    ( SELECT *, MAX( HistoryTally ) OVER ( PARTITION BY group_id ) MaxHistoryTally
        FROM AddHistoryTally ),
    
    SearchByMaxHistoryTally AS
    ( SELECT  group_id, id, FirstRecord, LastRecord, HistoryLength, HistoryTally
        FROM AddMaxHistoryTally
       WHERE HistoryTally = MaxHistoryTally ),
    
    AddHistoryTallyFrequency AS
    ( SELECT *, COUNT( HistoryTally ) OVER ( PARTITION BY group_id ) AS HistoryTallyFreq
        FROM SearchByMaxHistoryTally ),
    
    SearchByHistoryTallyFrequency AS
    ( SELECT group_id, id, FirstRecord, LastRecord, HistoryLength
        FROM AddHistoryTallyFrequency
       WHERE HistoryTallyFreq = 1 )
    
    SELECT * 
      FROM SearchByHistoryTallyFrequency;
    

    【讨论】:

    • 那么,如果我不能填充最顶部的部分(我有超过 300,000 个记录?我对 sql 比较陌生,那让我很失望。是'YourTable' 是我现在使用的表,还是我在 AddMaxLastRecord 之前从 'AS T' 创建的表?
    • 对不起,是的,只需取出整个T AS ... VALUES 部分并以WITH AddMaxLastRecord AS ( SELECT <struff> FROM <your actual table name here>... 开头
    猜你喜欢
    • 1970-01-01
    • 2022-01-13
    • 2020-08-26
    • 2014-05-23
    • 1970-01-01
    • 2018-06-04
    • 1970-01-01
    • 2021-09-15
    • 1970-01-01
    相关资源
    最近更新 更多