检索当前和最近的先前值(Oracle)

[英]Retrieving a current and most recent previous value (Oracle)


I'm facing a problem which I've spent a great deal of time trying to address, and although I have a solution, it's clunky and involves pl/sql processing, and I was wondering what others might come up with.

我遇到了一个问题,我花了很多时间试图解决这个问题,虽然我有一个解决方案,它很笨重,涉及pl / sql处理,我想知道别人可能会想出什么。

I'm working with a dataset that creates a new row every time a record is changed, thus maintaining a history. The most up-to-date version is then displayed in our application. Consider a table with the following data:

我正在使用一个数据集,每次更改记录时都会创建一个新行,从而保留历史记录。然后,在我们的应用程序中显示最新版本。考虑一个包含以下数据的表:

Person ID  Last_Name  Address_line1       Effective_Start_Date  Effective_End_Date
4913       Jones      1 First Street      03-aug-02             31-dec-12
4913       Cross      1 First Street      01-feb-02             02-aug-02
4913       Cross      86 Green Avenue     01-mar-01             31-jan-02
4913       Cross      87 Devonshire Road  01-jan-90             28-feb-02

As part of a report, I need to extract the details which have changed between a given set of dates. For instance, say I want to extract the current address_line1 and the previous address_line1 along with the date of change (effective_start_date when the new address was added). The caveat is that if other column data changes, this will create a new row too. For instance, in the example above, the last_name changed after the address changed.

作为报告的一部分,我需要提取在给定日期之间发生变化的细节。例如,假设我想提取当前的address_line1和之前的address_line1以及更改日期(添加新地址时的effective_start_date)。需要注意的是,如果其他列数据发生更改,这也会创建一个新行。例如,在上面的示例中,last_name在地址更改后更改。

Unfortunatey, the query must be generic so that it can be run as part of a report,i.e. not having to specify explicitly the effective start and end dates.

不幸的是,查询必须是通用的,以便它可以作为报告的一部分运行,即。不必明确指定有效的开始和结束日期。

Hope that all makes sense. Hopefully, you're all still with me. So, given the data-set above, I would expect to see the following results in my report:

希望一切都有道理。希望你们都和我在一起。因此,根据上面的数据集,我希望在我的报告中看到以下结果:

Person ID  Surname  Address_line1   Prev_Address_line1  Effective Start date of New Address Line 1
4913       Jones    1 First Street  86 Green Avenue     01-feb-02

My approach involves processing with pl/sql and looping over a considerable number of records but I was wondering if this can be done in a single sql query.

我的方法涉及使用pl / sql进行处理并循环遍历相当多的记录,但我想知道是否可以在单个sql查询中完成。

Does anyone have any ideas on whether this can be done using only sql?

有没有人对是否只使用sql可以做到这一点有任何想法?

2 个解决方案

#1


SELECT  personID, surname, address_line1,
        LAG(address_line1) OVER (PARTITION BY personID ORDER BY effectiveDate) AS prev_address_line1
FROM    mytable
WHERE   personID = :myid
ORDER BY
        effectiveDate

To return the last effective value, use:

要返回最后一个有效值,请使用:

SELECT  *
FROM    (
        SELECT  personID, surname, address_line1,
                LAG(address_line1) OVER (PARTITION BY personID ORDER BY effectiveDate) AS prev_address_line1,
                ROW_NUMBER() OVER (PARTITION BY personID ORDER BY effectiveDate DESC) AS rn,
        FROM    mytable
        WHERE   personID = :myid
        )
WHERE   rn = 1

#2


Don't Completely Understand your Question.

不要完全理解你的问题。

As part of a report, I need to extract the details which have changed between a given set of dates.

作为报告的一部分,我需要提取在给定日期之间发生变化的细节。

Versus

Unfortunatey, the query must be generic so that it can be run as part of a report,i.e. not having to specify explicitly the effective start and end dates.

不幸的是,查询必须是通用的,以便它可以作为报告的一部分运行,即。不必明确指定有效的开始和结束日期。

1) Does your Report provide a start date and End date, and look for changes within the range?. 2) Or are you looking for a general report for all changes with no constraints on date?

1)您的报告是否提供开始日期和结束日期,并查找范围内的变化? 2)或者您是否正在寻找所有更改的一般报告而没有约束日期?

Also

Assuming the Last Name Changed within the set of dates for which you are running the report.

假设在运行报告的日期集中更改了姓氏。

1) In your expected result are you completely ignoring the Fact that the Last_Name Changed

1)在您预期的结果中,您完全忽略了Last_Name更改的事实

2) Or will that be another row in your Report.

2)或者这将是您报告中的另一行。

of the type

这种类型

Person ID  Surname  Prev_Surname   Effective_Start_date_of_New Surname
4913       Jones    Cross          03-aug-02

3) Or is it even more complicated that you will capture all changes in one row.

3)或者您将捕获一行中的所有更改甚至更复杂。

Person ID  Surname  Prev_Surname   Effective_Start_date_of_New Surname Address_line1   Prev_Address_line1  Effective_Start_date_of_New_Address_Line_1 
4913       Jones    Cross          03-aug-02                           1 First Street  86 Green Avenue     01-feb-02

For a Report which shows each change, with the previous values for name and address. Try this. You can pick the last change by an outer select and choosing Change_rank =1

对于显示每个更改的报告,使用以前的名称和地址值。试试这个。您可以通过外部选择选择最后一次更改并选择Change_rank = 1

SELECT   PERSON_ID, CHANGED, NEW_VAL, OLD_VAL, EFFECTIVE_START_DATE
        -- The Rank just lets you pick by order of change incase you only want the last change, or last 2 changes
         ,RANK () OVER (ORDER BY EFFECTIVE_START_DATE DESC) CHANGE_RANK
    FROM (
          -- A select over Partition for each column where Old_val and New_Val need to be retrieved.
          -- In this Select the Address Column and Changed Address Are retrieved.
          SELECT PERSON_ID, 'ADDRESS_LINE1 CHANGE' CHANGED, ADDRESS_LINE1 NEW_VAL
                ,LEAD (ADDRESS_LINE1) OVER (PARTITION BY PERSON_ID ORDER BY EFFECTIVE_START_DATE DESC) AS OLD_VAL
                ,EFFECTIVE_START_DATE
            FROM TMP_RM_TEST
           -- Usually You want to run a report for a period,  Or remove this entire filter
          WHERE  EFFECTIVE_START_DATE BETWEEN TO_DATE (:REPORT_START_DATE, 'YYYYMMDD')
                                          AND TO_DATE (:REPORT_END_DATE, 'YYYYMMDD')
          UNION
          -- In this Select the Name Column and Changed Name Are retrieved.
          SELECT PERSON_ID, 'LAST_NAME CHANGE' CHANGED, LAST_NAME NEW_VAL
                ,LEAD (LAST_NAME) OVER (PARTITION BY PERSON_ID ORDER BY EFFECTIVE_START_DATE DESC) AS OLD_VAL
                ,EFFECTIVE_START_DATE
            FROM TMP_RM_TEST
           WHERE EFFECTIVE_START_DATE BETWEEN TO_DATE (:REPORT_START_DATE, 'YYYYMMDD')
                                          AND TO_DATE (:REPORT_END_DATE, 'YYYYMMDD') )
   -- Since the Partition By lists all changes over Person_ID, Irrespective of whether the Column changed, Filter to Remove Lines where no change was made to the Coloumn monitored
WHERE    NEW_VAL <> OLD_VAL
ORDER BY CHANGE_RANK
智能推荐

注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:http://www.itdaan.com/blog/2009/04/16/14e4e26241a10cab159c15f5897afa38.html



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告