我想在Oracle数据库表中选择与UserID关联的整数的MAX
值,以为具有相似UserID的用户生成下一个用户名。
UserID包含如下值。整数前没有固定的字符模式,因为字符串是用户名。
TKe10
TKe9
TKe12
TomKelly13
TomKelly9
PJames12
PJames7
我尝试使用以下查询,但始终将TKe9
或TomKelly9
或PJames7
作为MAX
的值。
SELECT * FROM
(SELECT MAX(UserID) from PV_USERS
WHERE REGEXP_LIKE (UserID, '^'|| '<some_user_id>'|| '[^A-
Za-z][0-9]*'));
我也尝试使用ORDER BY DESC WHERE ROWNUM<=1
,但它也提供相同的输出。
答案 0 :(得分:3)
您只需要提取ID的数字部分即可
regexp_substr(userid, '[0-9]*$')
,然后在找到最大值之前将其转换为数字(否则,您仍将进行字符串比较,并在10之前对9进行排序):
max(to_number(regexp_substr(userid, '[0-9]*$')))
并且您可能希望允许您检查的ID根目录根本不存在,您可以使用nvl()
或coalesce()
来做到这一点:
select coalesce(max(to_number(regexp_substr(userid, '[0-9]*$'))), 0) as max_num
from pv_users
where regexp_like(userid, '^'|| 'TomKelly'|| '[0-9]*');
MAX_NUM
----------
13
select coalesce(max(to_number(regexp_substr(userid, '[0-9]*$'))), 0) as max_num
from pv_users
where regexp_like(userid, '^'|| 'PJames'|| '[0-9]*');
MAX_NUM
----------
12
select coalesce(max(to_number(regexp_substr(userid, '[0-9]*$'))), 0) as max_num
from pv_users
where regexp_like(userid, '^'|| 'NewName'|| '[0-9]*');
MAX_NUM
----------
0
...,然后加1并附加回根以获取下一个ID。
根据您的业务规则,您可能希望使过滤器不区分大小写。
您应该注意,同时执行此操作的两个会话会看到相同的结果,因此两个会话都会尝试创建相同的ID,例如TomKelly14
。您要么需要序列化此生成操作,要么包括一个回退-就像在尝试将新值插入表中时检查是否违反PK,然后重复发生。
答案 1 :(得分:0)
with temp as
(
select 'Tke10' userid from dual
union all
select 'Tke9' userid from dual
union all
select 'Tke12' userid from dual
union all
select 'Tomkelly13' userid from dual
union all
select 'Tomkelly9' userid from dual
union all
select 'Pjames12' userid from dual
union all
select 'Pjames7' userid from dual
)
select A||B from (
select
substr(userid,1,instr(userid,to_number(regexp_substr(userid,'\d+$')))-1) A
,max(to_number(regexp_substr(userid,'\d+$'))) B
from temp
group by substr(userid,1,instr(userid,to_number(regexp_substr(userid,'\d+$')))-1)
)
;