sql >> Databáze >  >> RDS >> Mysql

Jak použít regulární výraz na výsledky dílčího dotazu?

Zkuste jeden z těchto dotazů:

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

nebo

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

Pokud není počet "koncových číslic" pevně daný, můžete také použít:

LIKE concat(u.phone_no, '%')

nebo

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

V tomto případě však možná budete muset použít SELECT DISTICT a.phone_no pokud je možné, že users.phone_no je podsekvence jiného users.phone_no (např. 99123 a 991234).

Aktualizovat

Po provedení několika testů s 10 000 řádky pro tabulku uživatelů a 100 000 řádky pro přijímací tabulku jsem došel k následujícímu dotazu:

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

fiddle

Tímto způsobem můžete použít REGEXP a stále mají skvělý výkon. Tento dotaz se v mém testovacím případě provede téměř okamžitě.

Logicky potřebujete pouze podmínky REGEXP. Ale na větších tabulkách může vypršet časový limit dotazu. Použití podmínky LIKE vyfiltruje sadu výsledků před kontrolou REGEXP. Ale ani použití LIKE dotazu nefunguje příliš dobře. Z nějakého důvodu MySQL nepoužívá kontrolu rozsahu pro spojení. Takže jsem přidal explicitní kontrolu rozsahu:

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

Pomocí této kontroly můžete odstranit podmínku LIKE z části JOIN.

Část UNION je náhradou za DISTICT. Zdá se, že MySQL překládá DISTINCT do příkazu GROUP BY, který nefunguje dobře. Použití UNION s prázdnou sadou výsledků nutí MySQL k odstranění duplikátů po SELECT. Tento řádek můžete odstranit, pokud použijete pevný počet koncových číslic.

Vzory REGEXP můžete upravit podle svých potřeb:

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

Pokud ke kontrole délky phone_no potřebujete pouze REGEXP, můžete také použít podmínku LIKE se zástupným znakem '_'.

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

nebo zkombinujte podmínku LIKE se zaškrtnutím STR_LENGTH.



  1. Práce s Java daty v Qlik Sense

  2. Datové typy kryptoměn MySQL?

  3. Najít volný pokoj (rezervační systém)

  4. MySQL - Jak vybrat řádky, kde je hodnota v poli?