获取最新变化的信息
Getting the information of the latest change
我有一个审计table,其中包含很多信息。我需要找到对每个项目的特定列进行最新更改的时间和人员。
我能够执行 returns 正确结果的查询,但我发现它是一个巨大的混乱。特别是因为我需要对很多不同的列执行此操作(我可能会使用 union 执行此操作)并将这些值与最新发布的值进行比较。无论如何......有没有比select的3级更好的方法?
create table Z_AUDIT
(
v CHAR(1) not null, -- A value that is part of a project (ex: project manager)
t DATE not null, -- Time of change
w VARCHAR2(10) not null, -- Who did the change
p VARCHAR2(10) -- Project
)
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 1', 'a', sysdate, 'bob');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 1', 'a', sysdate-1, 'judy');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 1', 'a', sysdate-2, 'bob');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 1', 'b', sysdate-3, 'judy');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 1', 'b', sysdate-4, 'bob');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 1', 'a', sysdate-5, 'judy');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 1', 'a', sysdate-6, 'bob');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 1', 'b', sysdate-7, 'judy');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 1', 'c', sysdate-8, 'bob');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 2', 'b', sysdate, 'bob');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 2', 'a', sysdate-1, 'judy');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 2', 'a', sysdate-2, 'bob');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 2', 'b', sysdate-3, 'judy');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 2', 'c', sysdate-4, 'bob');
-- Get the latest change from the rank 1
select p, w, t, current_value, previous_value
from ( -- Get only the changes with the where clause and get the rank
select i.p,
i.w,
i.t,
i.current_value,
i.previous_value,
rank() over(partition by i.p order by i.t desc) r
from ( -- Get the previous value for each audit record
select p,
w,
t,
v as current_value,
LAG(v, 1) OVER(partition by p ORDER BY t) as previous_value
from Z_AUDIT) i
where nvl(current_value, 'a') <> nvl(previous_value, 'a'))
where r = 1;
project 1, bob, 5/9/2020 7:08:55 AM, a, b
project 2, bob, 5/11/2020 7:12:39 AM, b, a
有几种更简单的写法。请注意,我使用 CTE 编写了两者,因为它们更易于阅读 (IMO)。您可以使用 FIRST_VALUE
:
WITH cp AS (
SELECT p, w, t, v AS curr,
LAG(v, 1, '') OVER (PARTITION BY p ORDER BY t) AS prev
FROM Z_AUDIT
)
SELECT DISTINCT p,
FIRST_VALUE(w) OVER (PARTITION BY p ORDER BY t DESC) AS w,
FIRST_VALUE(t) OVER (PARTITION BY p ORDER BY t DESC) AS t,
FIRST_VALUE(curr) OVER (PARTITION BY p ORDER BY t DESC) AS curr,
FIRST_VALUE(prev) OVER (PARTITION BY p ORDER BY t DESC) AS prev
FROM cp
WHERE curr != prev
或特定于 Oracle KEEP ... FIRST
:
WITH cp AS (
SELECT p, w, t, v AS curr,
LAG(v, 1, '') OVER (PARTITION BY p ORDER BY t) AS prev
FROM Z_AUDIT
)
SELECT p,
MIN(w) KEEP (DENSE_RANK FIRST ORDER BY t DESC) AS w,
MIN(t) KEEP (DENSE_RANK FIRST ORDER BY t DESC) AS t,
MIN(curr) KEEP (DENSE_RANK FIRST ORDER BY t DESC) AS curr,
MIN(prev) KEEP (DENSE_RANK FIRST ORDER BY t DESC) AS prev
FROM cp
WHERE curr != prev
GROUP BY p
两种情况下的输出都是:
P W T CURR PREV
project 1 bob 09-MAY-20 a b
project 2 bob 11-MAY-20 b a
上的演示(还包括原始查询的 CTE 版本)
我有一个审计table,其中包含很多信息。我需要找到对每个项目的特定列进行最新更改的时间和人员。
我能够执行 returns 正确结果的查询,但我发现它是一个巨大的混乱。特别是因为我需要对很多不同的列执行此操作(我可能会使用 union 执行此操作)并将这些值与最新发布的值进行比较。无论如何......有没有比select的3级更好的方法?
create table Z_AUDIT
(
v CHAR(1) not null, -- A value that is part of a project (ex: project manager)
t DATE not null, -- Time of change
w VARCHAR2(10) not null, -- Who did the change
p VARCHAR2(10) -- Project
)
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 1', 'a', sysdate, 'bob');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 1', 'a', sysdate-1, 'judy');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 1', 'a', sysdate-2, 'bob');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 1', 'b', sysdate-3, 'judy');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 1', 'b', sysdate-4, 'bob');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 1', 'a', sysdate-5, 'judy');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 1', 'a', sysdate-6, 'bob');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 1', 'b', sysdate-7, 'judy');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 1', 'c', sysdate-8, 'bob');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 2', 'b', sysdate, 'bob');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 2', 'a', sysdate-1, 'judy');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 2', 'a', sysdate-2, 'bob');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 2', 'b', sysdate-3, 'judy');
INSERT INTO Z_AUDIT (p, v, t, w) VALUES ('project 2', 'c', sysdate-4, 'bob');
-- Get the latest change from the rank 1
select p, w, t, current_value, previous_value
from ( -- Get only the changes with the where clause and get the rank
select i.p,
i.w,
i.t,
i.current_value,
i.previous_value,
rank() over(partition by i.p order by i.t desc) r
from ( -- Get the previous value for each audit record
select p,
w,
t,
v as current_value,
LAG(v, 1) OVER(partition by p ORDER BY t) as previous_value
from Z_AUDIT) i
where nvl(current_value, 'a') <> nvl(previous_value, 'a'))
where r = 1;
project 1, bob, 5/9/2020 7:08:55 AM, a, b
project 2, bob, 5/11/2020 7:12:39 AM, b, a
有几种更简单的写法。请注意,我使用 CTE 编写了两者,因为它们更易于阅读 (IMO)。您可以使用 FIRST_VALUE
:
WITH cp AS (
SELECT p, w, t, v AS curr,
LAG(v, 1, '') OVER (PARTITION BY p ORDER BY t) AS prev
FROM Z_AUDIT
)
SELECT DISTINCT p,
FIRST_VALUE(w) OVER (PARTITION BY p ORDER BY t DESC) AS w,
FIRST_VALUE(t) OVER (PARTITION BY p ORDER BY t DESC) AS t,
FIRST_VALUE(curr) OVER (PARTITION BY p ORDER BY t DESC) AS curr,
FIRST_VALUE(prev) OVER (PARTITION BY p ORDER BY t DESC) AS prev
FROM cp
WHERE curr != prev
或特定于 Oracle KEEP ... FIRST
:
WITH cp AS (
SELECT p, w, t, v AS curr,
LAG(v, 1, '') OVER (PARTITION BY p ORDER BY t) AS prev
FROM Z_AUDIT
)
SELECT p,
MIN(w) KEEP (DENSE_RANK FIRST ORDER BY t DESC) AS w,
MIN(t) KEEP (DENSE_RANK FIRST ORDER BY t DESC) AS t,
MIN(curr) KEEP (DENSE_RANK FIRST ORDER BY t DESC) AS curr,
MIN(prev) KEEP (DENSE_RANK FIRST ORDER BY t DESC) AS prev
FROM cp
WHERE curr != prev
GROUP BY p
两种情况下的输出都是:
P W T CURR PREV
project 1 bob 09-MAY-20 a b
project 2 bob 11-MAY-20 b a
上的演示(还包括原始查询的 CTE 版本)