次のクエリのいずれかを試してください:
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]+$'
または
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]+$'
「末尾の桁数」が固定されていない場合は、次を使用することもできます。
LIKE concat(u.phone_no, '%')
または
REGEXP concat('^', u.phone_no, '[0-9]*$')
ただし、この場合、SELECT DISTICT a.phone_no
を使用する必要がある場合があります users.phone_no
が可能であれば 他のusers.phone_no
のサブシーケンスです (例:99123および991234)。
更新
ユーザーテーブルに10K行、アドミッションテーブルに100K行を使用していくつかのテストを実行した後、次のクエリが表示されました。
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
このようにして、REGEXP
を使用できます それでも素晴らしいパフォーマンスがあります。このクエリは、私のテストケースではほぼ瞬時に実行されます。
論理的には、REGEXP条件のみが必要です。ただし、大きなテーブルでは、クエリがタイムアウトする可能性があります。 LIKE条件を使用すると、REGEXPチェックの前に結果セットがフィルタリングされます。しかし、LIKEを使用しても、クエリはあまりうまく機能しません。何らかの理由で、MySQLは結合に範囲チェックを使用しません。そこで、明示的な範囲チェックを追加しました:
ON a.phone_no >= u.phone_no
AND a.phone_no < CONCAT(u.phone_no, 'z')
このチェックを使用すると、JOINパーツからLIKE条件を削除できます。
UNIONパーツはDISTICTの代替品です。 MySQLはDISTINCTをGROUPBYステートメントに変換しているようですが、これはうまく機能しません。空の結果セットでUNIONを使用すると、SELECTの後に重複を削除するようにMySQLに強制します。末尾の数字を固定数で使用する場合は、その行を削除できます。
必要に応じてREGEXPパターンを調整できます:
...
AND a.phone_no REGEXP CONCAT('^', u.phone_no, '[0-9]{2}$')
...
AND u.phone_no REGEXP '^(99)+[0-9]{8}$'
...
phone_noの長さをチェックするためにREGEXPのみが必要な場合は、「_」プレースホルダーでLIKE条件を使用することもできます。
AND a.phone_no LIKE CONCAT(u.phone_no, '__')
...
AND u.phone_no LIKE '99________$'
または、LIKE条件をSTR_LENGTHチェックと組み合わせます。