Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Làm thế nào để sử dụng regexp trên các kết quả của một truy vấn phụ?

Hãy thử một trong các truy vấn sau:

SELECT a.phone_no
FROM admission a
JOIN users u on a.phone_no LIKE concat(u.phone_no, '__')
WHERE u.phone_no REGEXP  '^(99)+[0-9]+$'

hoặc

SELECT a.phone_no
FROM admission a
JOIN users u on a.phone_no REGEXP concat('^', u.phone_no, '[0-9]{2}$')
WHERE u.phone_no REGEXP  '^(99)+[0-9]+$'

Nếu số lượng "chữ số ở cuối" không cố định, bạn cũng có thể sử dụng:

LIKE concat(u.phone_no, '%')

hoặc

REGEXP concat('^', u.phone_no, '[0-9]*$')

Nhưng trong trường hợp này, bạn có thể cần sử dụng SELECT DISTICT a.phone_no nếu có thể là users.phone_no là một dãy con của users.phone_no khác (ví dụ:99123 và 991234).

Cập nhật

Sau khi chạy một số thử nghiệm với 10 nghìn hàng cho bảng người dùng và 100 nghìn hàng cho bảng nhập học, tôi đã đến với truy vấn sau:

SELECT a.phone_no
FROM admission a
JOIN users u 
    ON  a.phone_no >= u.phone_no
    AND a.phone_no < CONCAT(u.phone_no, 'z')
    AND a.phone_no LIKE CONCAT(u.phone_no, '%')
    AND a.phone_no REGEXP CONCAT('^', u.phone_no, '[0-9]*$')
WHERE   u.phone_no LIKE  '99%'
    AND u.phone_no REGEXP  '^(99)+[0-9]*$'
UNION SELECT 0 FROM (SELECT 0) dummy WHERE 0

fiddle

Bằng cách này, bạn có thể sử dụng REGEXP và vẫn có hiệu suất tuyệt vời. Truy vấn này thực thi gần như ngay lập tức trong trường hợp thử nghiệm của tôi.

Về mặt logic, bạn chỉ cần các điều kiện REGEXP. Nhưng trên các bảng lớn hơn, truy vấn có thể hết thời gian. Sử dụng điều kiện LIKE sẽ lọc kết quả được đặt trước khi kiểm tra REGEXP. Nhưng ngay cả khi sử dụng LIKE, truy vấn cũng không hoạt động tốt. Vì một số lý do MySQL không sử dụng kiểm tra phạm vi cho phép nối. Vì vậy, tôi đã thêm một kiểm tra phạm vi rõ ràng:

    ON  a.phone_no >= u.phone_no
    AND a.phone_no < CONCAT(u.phone_no, 'z')

Với việc kiểm tra này, bạn có thể xóa điều kiện LIKE khỏi phần THAM GIA.

Phần UNION thay thế cho DISTICT. MySQL dường như dịch DISTINCT thành một câu lệnh GROUP BY, điều này không hoạt động tốt. Sử dụng UNION với tập kết quả trống, tôi buộc MySQL phải loại bỏ các bản sao sau SELECT. Bạn có thể xóa dòng đó, nếu bạn sử dụng một số lượng chữ số ở cuối cố định.

Bạn có thể điều chỉnh các mẫu REGEXP theo nhu cầu của mình:

...
    AND a.phone_no REGEXP CONCAT('^', u.phone_no, '[0-9]{2}$')
...
    AND u.phone_no REGEXP  '^(99)+[0-9]{8}$'
...

Nếu bạn chỉ cần REGEXP để kiểm tra độ dài của phone_no, bạn cũng có thể sử dụng điều kiện LIKE với trình giữ chỗ '_'.

    AND a.phone_no LIKE CONCAT(u.phone_no, '__')
...
    AND u.phone_no LIKE '99________$'

hoặc kết hợp điều kiện LIKE với kiểm tra STR_LENGTH.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách định dạng ngày và giờ trong MySQL

  2. MySQL SubQuery - MySQL 3.23

  3. làm thế nào để truy vấn nhiều-nhiều?

  4. Tại sao MySQL sử dụng chỉ mục sai?

  5. Các chiến lược để đối phó với các yêu cầu thay đổi liên tục đối với các lược đồ MySQL?