1
create table numbers (number varchar(10));
insert into numbers (number) values
('9999999999'),
('5532003644'), 
('1212121205'),                                      
('1103220311'),                                     
('1121212128'),
('1234123425');                                    

Trying to SELECT only XY-XY-XY series from the database:

SELECT * FROM numbers
where number regexp '(.*([0-9])\2.*){3}'

Giving me results:

1212121205, 1121212128 & 1234123425


How 1234123425 is XY-XY-XY series?

DB-FIDDLE

13
  • 1
    What I find strange is that your query is returning all the results that don't match the regex... regex101.com/r/dQrJR7/1 Commented Jul 7, 2019 at 8:15
  • Are these your expected results? regex101.com/r/rMW7i1/1 Commented Jul 7, 2019 at 8:16
  • I don't understand this at all. How does ([0-9])\2 match XY? Shouldn't it match XX? Commented Jul 7, 2019 at 8:17
  • @Thefourthbird my expected results are only: 1212121205 & 1121212128 Commented Jul 7, 2019 at 8:17
  • @Barmar so what will be the regex that matches XY? Commented Jul 7, 2019 at 8:19

3 Answers 3

3

All your questions are interesting sql puzzles.
This solution also, does not involve regex:

select distinct n.number
from (
  select 1 start union all select 2  union all select 3 union all 
  select 4 union all select 5 
) s cross join numbers n
where 
  left(substring(n.number, s.start, 2), 1) <> right(substring(n.number, s.start, 2), 1)
  and
  n.number like concat(
    '%', substring(n.number, s.start, 2), 
    substring(n.number, s.start, 2),
    '%', substring(n.number, s.start, 2), '%'
  )

See the demo.
Results:

| number     |
| ---------- |
| 1212121205 |
| 1121212128 |
Sign up to request clarification or add additional context in comments.

7 Comments

If I want XYZ-XYZ, I tried this. Is that a correct way?
No, because I assume that you want all 3 chars of XYZ to be different or at least not all the same(?). This is more complicated.
Yes all different!
Instead of left(substring(n.number, s.start, 2), 1) <> right(substring(n.number, s.start, 3), 1) which compares the 1st and the last char of XY you must do 3 comparisons for XYZ, the 1st with the 2nd, the 1st with the 3d, and the 2nd with the 3d must all be different.
I think I am very near to the results: db-fiddle.com/f/2sdEBRtJw8jV9ap7be6FYD/4
|
1

Part of the problem is that you're not escaping the backslash. Backslash is both a string escape and a regexp escape; to get it into the regexp engine, you need to escape it for the string parser. Otherwise, \2 is treated as simply 2, so ([0-9])\2 matches any digit follwed by 2.

But you don't need to use a back-reference. \2 will match whatever ([0-9]) matched, which will make your code look for XX, not XY. I don't think there's a way to write a regexp where you match any character other than the back-reference.

1 Comment

I think, this will give me my expected results. Is there any issue in that?
0

This is not quite an answer, but you can do this with regular expressions. The problem is that MySQL does not support back references. Postgres, does, so the following does what you intend:

SELECT *
FROM numbers
WHERE number ~ '([0-9]{2}).*(\1).*(\1)'

Here is a dbfiddle.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.