Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Wie verwendet man Regexp für die Ergebnisse einer Unterabfrage?

Probieren Sie eine dieser Abfragen aus:

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

oder

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

Wenn die Anzahl der „nachgestellten Ziffern“ nicht festgelegt ist, können Sie auch verwenden:

LIKE concat(u.phone_no, '%')

oder

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

In diesem Fall müssen Sie jedoch möglicherweise SELECT DISTICT a.phone_no verwenden wenn es möglich ist, dass eine users.phone_no ist eine Unterfolge einer anderen users.phone_no (z. B. 99123 und 991234).

Aktualisieren

Nachdem ich einige Tests mit 10.000 Zeilen für die Benutzertabelle und 100.000 Zeilen für die Zulassungstabelle ausgeführt hatte, kam ich zu folgender Abfrage:

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

Geige

Auf diese Weise können Sie REGEXP verwenden und haben trotzdem super leistung. Diese Abfrage wird in meinem Testfall fast sofort ausgeführt.

Logischerweise benötigen Sie nur die REGEXP-Bedingungen. Bei größeren Tabellen kann es jedoch zu einer Zeitüberschreitung der Abfrage kommen. Die Verwendung einer LIKE-Bedingung filtert die Ergebnismenge vor der REGEXP-Prüfung. Aber selbst mit LIKE funktioniert die Abfrage nicht sehr gut. Aus irgendeinem Grund verwendet MySQL keine Bereichsprüfung für den Join. Also habe ich eine explizite Bereichsprüfung hinzugefügt:

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

Mit dieser Prüfung können Sie die LIKE-Bedingung aus dem JOIN-Teil entfernen.

Der UNION-Teil ist ein Ersatz für DISTICT. MySQL scheint DISTINCT in eine GROUP BY-Anweisung zu übersetzen, was nicht gut funktioniert. Durch die Verwendung von UNION mit einer leeren Ergebnismenge zwinge ich MySQL, Duplikate nach dem SELECT zu entfernen. Sie können diese Zeile entfernen, wenn Sie eine feste Anzahl an nachgestellten Ziffern verwenden.

Sie können die REGEXP-Muster an Ihre Bedürfnisse anpassen:

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

Wenn Sie REGEXP nur benötigen, um die Länge der Telefonnummer zu überprüfen, können Sie auch eine LIKE-Bedingung mit dem Platzhalter '_' verwenden.

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

oder kombinieren Sie eine LIKE-Bedingung mit einer STR_LENGTH-Prüfung.