Oracle - 从审计中获取多个条件的最新时间戳更新行 table

Oracle - Get latest timestamp updated rows for multiple criteria from audit table

我们有一个审计 table 跟踪不同 table 的变化以及 column_names、用户、时间戳、旧值和基于发票编号的新值.我需要检索一组特定的 tables 和特定发票编号的特定列集的最新审计数据(最后一个时间戳)。

Invoice_Number Table_Name Column_Name Timestamp User Old_Value New_Value
112 A 1 10-OCT-2021 12.00.00.111111 User1 7 6
112 B 1 11-OCT-2021 12.00.00.111111 User1 7 6
112 A 2 11-OCT-2021 12.00.00.111111 User1 7 6
114 B 1 12-OCT-2021 12.00.00.111111 User1 7 6
112 A 2 13-OCT-2021 12.00.00.111111 User1 7 6
122 B 2 13-OCT-2021 12.00.00.111111 User1 7 6
122 A 5 13-OCT-2021 12.00.00.111111 User1 7 6
112 A 2 15-OCT-2021 12.00.00.111111 User1 7 6
114 B 3 16-OCT-2021 12.00.00.111111 User1 7 6
112 B 2 18-OCT-2021 12.00.00.111111 User1 7 6
112 A 1 10-OCT-2021 12.00.00.111111 User1 7 6
142 B 1 11-OCT-2021 12.00.00.111111 User1 7 6
102 A 2 11-OCT-2021 12.00.00.111111 User1 7 6
184 B 1 12-OCT-2021 12.00.00.111111 User1 7 6
142 D 2 13-OCT-2021 12.00.00.111111 User1 7 6
118 C 2 18-OCT-2021 12.00.00.111111 User1 7 6

现在我需要获取发票编号 112 的最新更新记录,其中包含对 (Table A & Column 1, 2) 和 (Table B & column 1, 2).

我尝试使用排名,但不确定如何将其扩展到一列之外。

从 Oracle 12 开始,您可以使用 MATCH_RECOGNIZE:

SELECT *
FROM   (
  SELECT *
  FROM   table_name
  WHERE  invoice_number = 112
  AND    table_name IN ('A', 'B')
  AND    column_name IN (1, 2)
)
MATCH_RECOGNIZE (
  PARTITION BY /*invoice_number,*/ table_name, column_name
  ORDER     BY timestamp DESC
  ALL ROWS PER MATCH
  PATTERN (^ last_row)
  DEFINE  last_row AS 1 = 1
)

在早期版本中,可以使用ROW_NUMBER解析函数:

SELECT *
FROM   (
  SELECT t.*,
         ROW_NUMBER() OVER (
           PARTITION BY /*invoice_number,*/ table_name, column_name
           ORDER     BY timestamp DESC
         ) AS rn
  FROM   table_name t
  WHERE  invoice_number = 112
  AND    table_name IN ('A', 'B')
  AND    column_name IN (1, 2)
)
WHERE  rn = 1;

注意:由于您只有一个 invoice_number,因此不需要将其包含在 PARTITION BY 子句中;但是,如果您有多个 invoice_number,那么您会想要。

其中,对于示例数据:

CREATE TABLE table_name (Invoice_Number, Table_Name, Column_Name, Timestamp, "USER", Old_Value, New_Value) AS
SELECT 112, 'A', 1, TIMESTAMP '2021-10-10 12:00:00.111111', 'User1', 7, 6 FROM DUAL UNION ALL
SELECT 112, 'B', 1, TIMESTAMP '2021-10-11 12:00:00.111111', 'User1', 7, 6 FROM DUAL UNION ALL
SELECT 112, 'A', 2, TIMESTAMP '2021-10-11 12:00:00.111111', 'User1', 7, 6 FROM DUAL UNION ALL
SELECT 114, 'B', 1, TIMESTAMP '2021-10-12 12:00:00.111111', 'User1', 7, 6 FROM DUAL UNION ALL
SELECT 112, 'A', 2, TIMESTAMP '2021-10-13 12:00:00.111111', 'User1', 7, 6 FROM DUAL UNION ALL
SELECT 122, 'B', 2, TIMESTAMP '2021-10-13 12:00:00.111111', 'User1', 7, 6 FROM DUAL UNION ALL
SELECT 122, 'A', 5, TIMESTAMP '2021-10-13 12:00:00.111111', 'User1', 7, 6 FROM DUAL UNION ALL
SELECT 112, 'A', 2, TIMESTAMP '2021-10-15 12:00:00.111111', 'User1', 7, 6 FROM DUAL UNION ALL
SELECT 114, 'B', 3, TIMESTAMP '2021-10-16 12:00:00.111111', 'User1', 7, 6 FROM DUAL UNION ALL
SELECT 112, 'B', 2, TIMESTAMP '2021-10-18 12:00:00.111111', 'User1', 7, 6 FROM DUAL UNION ALL
SELECT 112, 'A', 1, TIMESTAMP '2021-10-10 12:00:00.111111', 'User1', 7, 6 FROM DUAL UNION ALL
SELECT 142, 'B', 1, TIMESTAMP '2021-10-11 12:00:00.111111', 'User1', 7, 6 FROM DUAL UNION ALL
SELECT 102, 'A', 2, TIMESTAMP '2021-10-11 12:00:00.111111', 'User1', 7, 6 FROM DUAL UNION ALL
SELECT 184, 'B', 1, TIMESTAMP '2021-10-12 12:00:00.111111', 'User1', 7, 6 FROM DUAL UNION ALL
SELECT 142, 'D', 2, TIMESTAMP '2021-10-13 12:00:00.111111', 'User1', 7, 6 FROM DUAL UNION ALL
SELECT 118, 'C', 2, TIMESTAMP '2021-10-18 12:00:00.111111', 'User1', 7, 6 FROM DUAL

输出:

TABLE_NAME COLUMN_NAME TIMESTAMP INVOICE_NUMBER USER OLD_VALUE NEW_VALUE
A 1 10-OCT-21 12.00.00.111111000 112 User1 7 6
A 2 15-OCT-21 12.00.00.111111000 112 User1 7 6
B 1 11-OCT-21 12.00.00.111111000 112 User1 7 6
B 2 18-OCT-21 12.00.00.111111000 112 User1 7 6

db<>fiddle here