Mysql
 sql >> Base de données >  >> RDS >> Mysql

Comment utiliser regexp sur les résultats d'une sous-requête ?

Essayez l'une de ces requêtes :

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

ou

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 le nombre de "chiffres de fin" n'est pas fixe, vous pouvez également utiliser :

LIKE concat(u.phone_no, '%')

ou

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

Mais dans ce cas, vous devrez peut-être utiliser SELECT DISTICT a.phone_no s'il est possible qu'un users.phone_no est une sous-séquence d'un autre users.phone_no (par exemple 99123 et 991234).

Mettre à jour

Après avoir exécuté quelques tests avec 10 000 lignes pour la table des utilisateurs et 100 000 lignes pour la table d'admission, je suis arrivé à la requête suivante :

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

violon

De cette façon, vous pouvez utiliser REGEXP et ont toujours d'excellentes performances. Cette requête s'exécute presque instantanément dans mon cas de test.

Logiquement, vous n'avez besoin que des conditions REGEXP. Mais sur des tables plus grandes, la requête peut expirer. L'utilisation d'une condition LIKE filtrera le jeu de résultats avant la vérification REGEXP. Mais même en utilisant LIKE, la requête ne fonctionne pas très bien. Pour une raison quelconque, MySQL n'utilise pas de vérification de plage pour la jointure. J'ai donc ajouté une vérification de plage explicite :

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

Avec cette vérification, vous pouvez supprimer la condition LIKE de la partie JOIN.

La partie UNION remplace DISTICT. MySQL semble traduire DISTINCT en une instruction GROUP BY, qui ne fonctionne pas bien. En utilisant UNION avec un jeu de résultats vide, je force MySQL à supprimer les doublons après le SELECT. Vous pouvez supprimer cette ligne si vous utilisez un nombre fixe de chiffres de fin.

Vous pouvez ajuster les modèles REGEXP à vos besoins :

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

Si vous avez seulement besoin de REGEXP pour vérifier la longueur du phone_no, vous pouvez également utiliser une condition LIKE avec l'espace réservé '_'.

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

ou combiner une condition LIKE avec une vérification STR_LENGTH.