2017-06-26 2 views
0

Angesichts einer Spalte von Strings (Passwörter) in MySQL und einen Wert N gegeben, ich bin auf der Suche nach einem SQL-Weg, um die Häufigkeit der einzelnen N-Gramm (Teilstrings der Länge n).MySQL einzelne Spalte n-gram Split und zählen

Es ist wichtig, den Code in MySQL zu behalten, denn in anderen Umgebungen, die ich habe, wird es mit Speicherüberlauf kommen.

Der einzige Arbeits Ansatz I durch die Annahme, begrenzte Länge der Saite (legit Annahme) ist mittlerweile gefunden, select separat von verschiedenen Orten Teil Extrahieren union und dann group by und count, wie dies (für 9-Gramm von 13 Zeichen):

Select 
    nueve, 
    count(*) as density, 
    avg(location) as avgloc 

From 
    (select 
     mid(pass, 1, 9) as nueve, 1 as location 
    from 
     passdata 
    where 
     length(pass) >= 9 and length(pass) <= 13 UNION ALL select 
     mid(pass, 2, 9), 2 as location 
    from 
     passdata 
    where 
     length(pass) >= 10 and length(pass) <= 13 UNION ALL select 
     mid(pass, 3, 9), 3 as location 
    from 
     passdata 
    where 
     length(pass) >= 11 and length(pass) <= 13 UNION ALL select 
     mid(pass, 4, 9), 4 as location 
    from 
     passdata 
    where 
     length(pass) >= 12 and length(pass) <= 13 UNION ALL select 
     mid(pass, 5, 9), 5 as location 
    from 
     passdata 
    where 
     length(pass) = 13) as nueves 
group by nueve 
order by density DESC 

Die Ergebnisse suchen wie folgt aus:

nueve  density avgloc 
123456789 1387 2.4564 
234567890 193  2.7306 
987654321 141  2.0355 
password1 111  1.7748 
123123123 92  1.913 
liverpool 89  1.618 
111111111 86  2.2791 

wo nueve ist das 9-Gramm, density die Zahl der Erscheinungen ist, und avgloc wird die mittlere Startposition in der Zeichenfolge

Irgendwelche Vorschläge, die Abfrage zu verbessern? Ich mache das gleiche für andere N-Gramme auch.

Danke!

Antwort

1

Erstellen Sie eine Tabelle mit allen Zahlen von 1 bis zur maximalen Länge der Kennwörter. Sie können sich dann damit verbinden, um die Teilstringpositionen zu erhalten.

SELECT nueve, COUNT(*) AS density, AVG(location) as avgloc 
FROM (
    SELECT MID(p.pass, n.num, @N) AS nueve, n.num AS location 
    FROM passdata AS p 
    JOIN numbers_table AS n ON LENGTH(p.pass) >= (@N + n.num - 1) 
) AS x 
GROUP BY nueve 
ORDER BY density DESC 
+0

Danke, das ist sehr schlau! Ich denke, ich würde es auch für Wortzählungen verwenden. – Dimgold

+0

Es ist nützlich für jede Art von numerischer Iteration, da SQL nur mit dem Joinieren echte Möglichkeiten für Iterationen bietet. – Barmar

Verwandte Themen