Vinzenz Mai: MySQL : mit regulären Ausdrücken Wörter für Buchstaben suchen

Beitrag lesen

Hallo,

Tabelle: word

ID | word
---+-----
1  | RETTE
2  | RETTER
3  | RETTEN

es ist ganz sicher aus Gründen der Leseoptimierung sinnvoll, die Zeichenlänge des Wortes (redundant) in einer eigenen Spalte abzuspeichern:

ID | word    | length
---+---------+-------
1  | RETTE   |  5
2  | RETTER  |  6
3  | RETTEN  |  6

Tabelle: word_letter
n = Häufigkeit der Buchstaben in dem Wort

ID_word | letter | n
--------+--------+---
1       | R      | 1
1       | E      | 2
1       | T      | 2
2       | R      | 2
2       | E      | 2
2       | T      | 2
3       | R      | 1
3       | E      | 2
3       | T      | 2
3       | N      | 1

  1. Schritt:
    nach der ersten Abfrage sollen alle "Wörter" mit einer bestimmten Länge übrig bleiben

die Abfrage dazu vereinfacht sich zu

SELECT             -- Gib mir  
    ID,            --    ID,  
    word           --    wort  
FROM               -- aus der Tabelle  
    word           --    word  
WHERE              -- wobei nur Wörter mit der  
    length = 6     --    Zeichenlänge 6 berücksichtigt werden sollen.  

Dies ist ganz sicher performanter als ein Join mit Gruppierung und HAVING-Klausel, da sonst *alle* Datensätze berücksichtigt werden müssen.

und folgende Tabelle übergeben werden.

ID_word | letter | n
--------+--------+---
2       | R      | 2
2       | E      | 2
2       | T      | 2
3       | R      | 1
3       | E      | 2
3       | T      | 2
3       | N      | 1

ein einfacher Join mit word_letter

SELECT                  -- Gib mir  
    w.ID      ID_word,  --     die IDs der Worte  
    wl.letter letter,   --     die darin vorkommenden Buchstaben  
    wl.n      n         --     und ihre Anzahl  
FROM                    -- aus der Tabelle  
    word w              --     word (als w angesprochen),  
INNER JOIN              -- die mit der Tabelle  
    word_letter wl      --     word_letter (als wl angesprochen)  
ON                      -- über die Spalten  
    w.ID = wl.ID        --     ID (in beiden Tabellen) verknüpft ist  
WHERE                   -- wobei nur die Worte interessieren,  
    w.length = 6        --     die 6 Zeichen lang sind.  

("RETTE" ist damit schonmal raus)

Diese "Tabelle" kann die Grundlage entweder diverser Selfjoins oder halt diverser Subselects sein. Da die Anzahl der Buchstaben jeweils unterschiedlich ist, kannst Du das dritte Beispiel nicht anwenden, sondern musst Dich mit dem zweiten begnügen :-(

  1. Schritt:
    im zweiten Schritt bleiben noch alle Wörter, in denen "R" zweimal vorkommt:

ID_word | letter | n
--------+--------+---
2       | R      | 2
2       | E      | 2
2       | T      | 2

Was performanter ist:
Subselect über die ganze word_letter-Tabelle oder über obige Abfrage, das musst Du mit Deinen Daten selbst durchtesten (EXPLAIN hilft Dir dabei):

SELECT  
    w.word  
FROM  
    word w  
WHERE  
    w.length = 6  
AND  
    w.ID IN (  
        SELECT  
             wl.ID  
        FROM  
             word_letter wl  
        WHERE  
             letter = 'R'  
        AND  
             n = 2  
    )  
AND  
    w.ID IN (  
        SELECT  
             wl2.ID  
        FROM  
             word_letter wl2  
        WHERE  
             letter = 'E'  
        AND  
             n = 2  
    )  

Beachte dabei die Hinweise im Handbuchkapitel Optimizing Subqueries, aber insbesondere den ersten Satz.

Freundliche Grüße

Vinzenz