I have a list of telephone number (in ORACLE SQL), et i have to check in this list, if a number contains 4 times a number consecutively. In that case, i have to set the value to null. Exemple:
TEL | STATUS |
---|---|
012345678 | OK |
021444458 | NULL |
339547214 | OK |
111105874 | NULL |
How can i check this? Thank you
CodePudding user response:
Here's how I understood it (read comments within code):
SQL> with test (tel) as
2 -- sample data
3 (select '012345678' from dual union all
4 select '021444458' from dual union all
5 select '339547214' from dual union all
6 select '111105874' from dual
7 ),
8 cons (dig) as
9 -- generated consecutive digits, 0000, 1111, ..., 9999
10 (select lpad(level - 1, 4, level - 1)
11 from dual
12 connect by level <= 10
13 ),
14 temp as
15 -- check whether any TEL number constains consecutive digits
16 (select t.tel,
17 c.dig,
18 case when instr(t.tel, c.dig) > 0 then 'NOK'
19 else 'OK'
20 end as status
21 from test t cross join cons c
22 )
23 -- finally, two groups: those that are OK (don't contain consecutive digits) and ...
24 select a.tel, 'OK'
25 from test a
26 where not exists (select null from temp b
27 where b.tel = a.tel
28 and b.status = 'NOK'
29 )
30 union all
31 -- ... those that contain 4 consecutive digits
32 select a.tel, 'NULL'
33 from test a
34 where exists (select null from temp b
35 where b.tel = a.tel
36 and b.status = 'NOK'
37 )
38 order by tel;
TEL 'OK'
--------- ----
012345678 OK
021444458 NULL
111105874 NULL
339547214 OK
SQL>
[EDIT: converting to UPDATE]
Data before:
SQL> SELECT * FROM test;
TEL STATUS
--------- ----------
012345678
021444458
339547214
111105874
Update:
SQL> UPDATE test t
2 SET t.status =
3 (WITH
4 cons (dig)
5 AS
6 -- generated consecutive digits, 0000, 1111, ..., 9999
7 ( SELECT LPAD (LEVEL - 1, 4, LEVEL - 1)
8 FROM DUAL
9 CONNECT BY LEVEL <= 10),
10 temp
11 AS
12 -- check whether any TEL number constains consecutive digits
13 (SELECT t.tel,
14 c.dig,
15 CASE
16 WHEN INSTR (t.tel, c.dig) > 0 THEN 'NOK'
17 ELSE 'OK'
18 END AS status
19 FROM test t CROSS JOIN cons c),
20 -- finally, two groups: those that are OK (don't contain consecutive digits) and ...
21 temp2
22 AS
23 (SELECT a.tel, 'OK' status
24 FROM test a
25 WHERE NOT EXISTS
26 (SELECT NULL
27 FROM temp b
28 WHERE b.tel = a.tel
29 AND b.status = 'NOK')
30 UNION ALL
31 -- ... those that contain 4 consecutive digits
32 SELECT a.tel, 'NULL' status
33 FROM test a
34 WHERE EXISTS
35 (SELECT NULL
36 FROM temp b
37 WHERE b.tel = a.tel
38 AND b.status = 'NOK'))
39 SELECT t2.status
40 FROM temp2 t2
41 WHERE t2.tel = t.tel);
4 rows updated.
Data after:
SQL> SELECT * FROM test;
TEL STATUS
--------- ----------
012345678 OK
021444458 NULL
339547214 OK
111105874 NULL
SQL>
CodePudding user response:
As another solution, you could use regexp_like to get the job done. The regex expression (\d)(\1){3,} will match any digit that repeats consecutively at least four times.
with t (TEL) as (
select '012345678' from dual union all
select '021444458' from dual union all
select '339547214' from dual union all
select '111105874' from dual
)
select TEL, case when not regexp_like(TEL, '(\d)(\1){3,}') then 'OK' end STATUS
from t ;
Then, update would be like this
UPDATE test t
SET t.status = case when not regexp_like(TEL, '(\d)(\1){3,}') then 'OK' else null end
;