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
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.