问题
I've a table of users and one of the columns is User_ID (naming policy = first letter of first name and rest is the last name. If a name is exists, then increment by 1).
For example: John Doe -> user_id=jdoe
If jdoe already exists then user_id = jdoe1
The input for the query is a basic user_id (e.g. jdoe) I would like to scan the table and for the output of the query to be: a new distinct value of user_id.
If the table has the following values:
jdoe
jdoe1
jdoe2
jdoe3
The output should be jdoe4
.
Any help will be appreciated.
Thanks
P.S
Changes to the table are not allowed.
The value from the query is being used with another system (active directory)
回答1:
This uses an inline view to get the user_id
and numeric suffix for any thing matching your base ID value, and then decides whether it can use the unadorned base value (if max(user_id)
is null then there was nothing similar already), and if not adds an incremented suffix.
That suffix is based on the highest existing suffix, but if you only have the base name so far (jdoe
with no number) then max(suffix)
is null, so the nvl()
turns that into a zero before adding one.
select decode(max(user_id), null, :base, :base || (nvl(max(suffix), 0) + 1))
as new_user_id
from (
select user_id, regexp_replace(user_id, '^[[:alpha:]]*', null) as suffix
from users
where regexp_like(user_id, '^' || :base || '[^[:alpha:]]*$')
);
With a starting users table that contains:
jdoe
jdoe1
jdoe2
jdoe3
jdoes6
adoe
... changing the bind variable to supply the basic string gives you:
jdoe -> jdoe4
jdoes -> jdoes7
adoe -> adoe1
adoes -> adoes
回答2:
EDIT: This is corrected based on a comment from Alex Poole. Assuming that base names/initials doesn't contain numbers.
WITH tab
AS (SELECT 'jdoe' name FROM DUAL
UNION ALL
SELECT 'jdoe1' FROM DUAL
UNION ALL
SELECT 'jdoe2' FROM DUAL
UNION ALL
SELECT 'jdoe3' FROM DUAL
UNION ALL
SELECT 'jdoes7' FROM DUAL
UNION ALL
SELECT 'jjdoe66' FROM DUAL)
SELECT :newName || TO_CHAR (MAX (id) + 1)
FROM (SELECT NVL (REGEXP_REPLACE (name, '[^0-9]'), 0) id
FROM tab
WHERE REGEXP_LIKE (name, '^' || :newName || '[0-9]'));
REGEXP_REPLACE
with [^0-9]
removes all non numerical characters.
REGEXP_LIKE
with [0-9]
only shows matches with following numbers. ^
denotes at the beginning of.
:newName
is a bind variable.
来源:https://stackoverflow.com/questions/29747674/oracle-11g-find-out-a-new-distinct-value