sql >> Base de Datos >  >> RDS >> Mysql

¿Cómo usar expresiones regulares en los resultados de una subconsulta?

Pruebe una de estas consultas:

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]+$'

o

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]+$'

Si el número de "dígitos finales" no es fijo, también puede usar:

LIKE concat(u.phone_no, '%')

o

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

Pero en este caso, es posible que deba usar SELECT DISTICT a.phone_no si es posible que un users.phone_no es una subsecuencia de otro users.phone_no (por ejemplo, 99123 y 991234).

Actualizar

Después de ejecutar algunas pruebas con 10 000 filas para la tabla de usuarios y 100 000 filas para la tabla de admisión, llegué a la siguiente consulta:

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

violín

De esta manera puedes usar REGEXP y todavía tienen un gran rendimiento. Esta consulta se ejecuta casi instantáneamente en mi caso de prueba.

Lógicamente solo necesitas las condiciones REGEXP. Pero en tablas más grandes, la consulta podría agotarse. El uso de una condición LIKE filtrará el conjunto de resultados antes de la verificación REGEXP. Pero incluso usando LIKE la consulta no funciona muy bien. Por alguna razón, MySQL no usa una verificación de rango para la unión. Así que agregué una verificación de rango explícita:

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

Con esta verificación, puede eliminar la condición LIKE de la parte JOIN.

La parte UNION es un reemplazo para DISTICT. MySQL parece traducir DISTINCT en una instrucción GROUP BY, que no funciona bien. Usando UNION con un conjunto de resultados vacío, obligo a MySQL a eliminar duplicados después de SELECCIONAR. Puede eliminar esa línea, si usa un número fijo de dígitos finales.

Puede ajustar los patrones REGEXP a sus necesidades:

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

Si solo necesita REGEXP para verificar la longitud de phone_no, también puede usar una condición LIKE con el marcador de posición '_'.

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

o combine una condición LIKE con una verificación STR_LENGTH.