我需要根据给定记录的某个版本提取数据。我想根据ID的第一个用户的最终保存提取最大版本。这可能吗?
- 在我的模拟中,我的版本号为1,2,3,但数字实际上是在我的数据库中随机分配的。
我正在尝试使用:
select id, max(version) over partition by id
from t1
这是我的数据: T1
ID User Version
1 123 1
1 123 2
1 123 3
1 456 4
1 456 5
1 789 6
2 452 1
2 452 2
2 587 3
2 123 4
3 901 1
3 767 2
3 456 3
这是我想要提取的内容: T1
ID User MaxVersion
1 123 3
2 452 2
3 901 1
答案 0 :(得分:2)
我想你想要:
select t1.*
from (select id,
row_number() over (partition by id, user order by version desc) as seqnum,
max(user) keep (dense_rank first order by version) over (partition by id) as first_user
from t1
) t1
where seqnum = 1 and user = first_user;
您需要单独查找用户和最后一条记录。
编辑:
如果您需要"首先"最终版本,我会选择:
select t1.*
from (select t1.*,
min(case when user <> first_user then version end) over (partition by id) as last_version_plus_1
from (select id,
max(user) keep (dense_rank first order by version) over (partition by id) as first_user
from t1
) t1
where seqnum = 1 and user = first_user
) t1
where version < max_version;
或者,您可以使用相关子查询执行此操作:
select t1.*
from t1
where t1.user = (select min(tt1.user) keep (dense_rank first order by tt1.version)
from t1 tt1
where tt1.id = t1.id
) and
t1.version < (select min(tt1.version)
from t1 tt1
where tt1.id = t1.id and tt1.user <> t1.user
);
这是老式的&#34;方法(预解析函数)。但它完全捕捉到了这个想法。第一个确保用户是第一个用户。第二个确保版本来自该用户的第一个记录。
答案 1 :(得分:1)
在Oracle 12.1及更高版本中,match_recognize
可以快速完成此类要求。 (与分析函数解决方案相比,一个好处是max(version)
仅为每个ID
的一个用户计算,而不需要子查询来实现此效率。
match_recognize
子句按id
分区,并在每个id
内按版本(升序)排序。然后“匹配”仅来自分区的开头(^
子句中的pattern
),并且仅包含与第一行具有相同id
的行(在按id
分区。该id
的所有其他行都将被忽略。然后收集输出的最后一个版本值。
注意:这假定,如果对于给定的ID,第一个用户更改为第二个,第三个等,但随后恢复为第一个用户,中的最高版本号需要> FIRST 该用户的行集。如果需要该用户的所有行中的最高版本号,则可以相应地更改查询(特别是PATTERN子句需要更改)。
with
inputs ( id, usr, ver ) as (
select 1, 123, 1 from dual union all
select 1, 123, 2 from dual union all
select 1, 123, 3 from dual union all
select 1, 456, 4 from dual union all
select 1, 456, 5 from dual union all
select 1, 789, 6 from dual union all
select 2, 452, 1 from dual union all
select 2, 452, 2 from dual union all
select 2, 587, 3 from dual union all
select 2, 123, 4 from dual union all
select 3, 901, 1 from dual union all
select 3, 767, 2 from dual union all
select 3, 456, 3 from dual
)
-- End of simulated inputs (not part of the solution).
-- SQL query begins BELOW THIS LINE. Use your actual table and column names.
select id, usr, ver
from inputs
match_recognize (
partition by id
order by ver
measures last(usr) as usr,
last(ver) as ver
pattern ( ^ a+ )
define a as usr = first(usr)
);
ID USR VER
-- --- ---
1 123 3
2 452 2
3 901 1
修改强>:
为了完整性,如果用户可能出现在非连续行上,那么PATTERN应该是什么样子,并且对于给定id
,该用户的最后一次出现(即使非连续)必须是考虑:
...
pattern ( ^ a (x* a)? )
...
此处分区中的第一行是 a ,如果相同的用户再次出现在同一id
,则至少还有一个 a 行; last 这样的行被模式的可选部分捕获,并且x*
上有贪婪的匹配。
答案 2 :(得分:0)
select rnk,id, user,mv from (select rownum as rnk,id,user,max(version) from T1
group by id, user )where rnk=1;