sql >> Database >  >> RDS >> Mysql

Hoe regexp te gebruiken op de resultaten van een subquery?

Probeer een van deze zoekopdrachten:

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

of

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

Als het aantal "volgende cijfers" niet vaststaat, kunt u ook het volgende gebruiken:

LIKE concat(u.phone_no, '%')

of

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

Maar in dit geval moet u mogelijk SELECT DISTICT a.phone_no . gebruiken als het mogelijk is dat een users.phone_no is een vervolg op een andere users.phone_no (bijv. 99123 en 991234).

Bijwerken

Na het uitvoeren van enkele tests met 10.000 rijen voor de gebruikerstabel en 100.000 rijen voor de toelatingstabel, kwam ik tot de volgende vraag:

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

viool

Op deze manier kunt u REGEXP . gebruiken en nog steeds geweldige prestaties. Deze query wordt vrijwel onmiddellijk uitgevoerd in mijn testcase.

Logischerwijs heb je alleen de REGEXP voorwaarden nodig. Maar op grotere tabellen kan de query een time-out krijgen. Als u een LIKE-voorwaarde gebruikt, wordt de resultaatset gefilterd vóór de REGEXP-controle. Maar zelfs met LIKE presteert de query niet erg goed. Om de een of andere reden gebruikt MySQL geen bereikcontrole voor de join. Dus ik heb een expliciete bereikcontrole toegevoegd:

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

Met deze controle kun je de LIKE-voorwaarde uit het JOIN-gedeelte verwijderen.

Het UNION-onderdeel is een vervanging voor DISTICT. MySQL lijkt DISTINCT te vertalen in een GROUP BY-statement, wat niet goed presteert. Door UNION te gebruiken met een lege resultaatset, dwing ik MySQL om duplicaten te verwijderen na de SELECT. U kunt die regel verwijderen als u een vast aantal volgcijfers gebruikt.

U kunt de REGEXP-patronen aanpassen aan uw behoeften:

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

Als je alleen REGEXP nodig hebt om de lengte van het phone_no te controleren, kun je ook een LIKE-voorwaarde gebruiken met de tijdelijke aanduiding '_'.

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

of combineer een LIKE-voorwaarde met een STR_LENGTH-controle.



  1. Spelersrangschikking per categorie over maanden

  2. Een waarde van een versleuteld veld uniek maken

  3. MySQL:hoe voeg ik een kolom toe als deze nog niet bestaat?

  4. Wat gebeurt er als ik een MySQL-kolom laat vallen zonder eerst de index te laten vallen?