2009-07-19 7 views
3

Ich versuche, das folgende zu erreichen. Nehmen wir an, wir haben eine Tabelle, die diese Felder enthält (ID, Inhalt)MySQL, wählen Sie Datensätze mit mindestens X Zeichen passend

1 | Apfel

2 | Ananas

3 | Anwendung

4 | Nation

Jetzt suche ich nach einer Funktion, die mir alle möglichen gemeinsamen Übereinstimmungen sagen wird. Wenn das Argument beispielsweise "3" ist, gibt die Funktion alle möglichen Zeichenfolgen aus 3 Zeichen zurück, die in mehr als einem Datensatz vorkommen.

In diesem Fall erhalte ich "app", "ppl", "ple", "ati", "tio", "Ion"

Wenn das Argument "4" ist, erhalte ich: „Appl “, "pple", "atio", "Kapitel 5"

Wenn die arugment ist "", erhalte ich: "Apfel", "ation"

Wenn das Argument "6" ist, nohting zurückgegeben .

Bis jetzt habe ich keine Funktion gefunden, die dies erreicht.

Thx!

Einige zusätzliche Informationen: Ich verwende dies in einem PHP-Skript mit einer MySQL-Datenbank. Ich möchte nur die Anzahl der Zeichen als Argument angeben und natürlich die Tabelle, in der gesucht werden soll.

+0

was möchten Sie als Argument neben der Zahl, die die Länge darstellt, als Abfrage an die Abfrage senden? Aus welcher Kodiersprache wird dies abgeleitet? –

Antwort

0

Eine offensichtliche Option ist die Verwendung von REGEX. Ich habe keine vorherige Erfahrung in diesem, aber das könnte Ihnen helfen: http://dev.mysql.com/doc/refman/5.1/en/regexp.html

Sie müssen einen geeigneten Ausdruck finden, um zu entsprechen, was Sie brauchen.

+0

Es ist nicht sehr offensichtlich. Wir sprechen über eine zufällige Regex und vergleichen das Ergebnis mit allen anderen Datensätzen in der Tabelle. Ich kann kein SQL mit regex dafür sehen. – PatrikAkerstrand

+0

Wie oben erwähnt, ist dies nur ein kleiner Teil der Lösung. Ich kenne die Charaktere nicht, nach denen ich Ausschau halten muss. Mit 5 Zeichen ergibt dies 2^5 Regexp-Abfragen, die ich ausführen sollte, wenn ich es zufällig mache. Leider ist dies für dieses Problem nicht geeignet. – Digits

+0

@Machine Ich denke, ich habe die Frage nicht vollständig verstanden, bis ich sie erneut gelesen habe. Einverstanden, meine "offensichtliche" Option war überhaupt nicht anwendbar. Ich glaube wirklich nicht, dass dies erreicht werden kann, indem nur SQL-Abfragen verwendet werden, aber ich würde sicherlich gerne falsch bewiesen werden. –

3

Nun, das ist irgendwie hässlich, aber es funktioniert gut. Es ist generisches SQL und funktioniert in jeder Umgebung. Generieren Sie einfach eine Anzahl von Selects einer Teilzeichenfolge, die größer ist als die maximale Länge des Feldes, das Sie lesen. Ändern Sie die Zahl 50 in der Funktion zu einer Zahl, die Ihre Feldlänge überschreitet. Es kann eine wirklich lange Abfrage zurückgeben, aber wie gesagt, es wird gut funktionieren. Hier ist ein Beispiel in Python:

import sqlite3 

c = sqlite3.connect('test.db') 

c.execute('create table myTable (id integer, content varchar[50])') 
for id, content in ((1,'apple'),(2,'pineapple'),(3,'application'),(4,'nation')): 
    c.execute('insert into myTable values (?,?)', [id,content]) 

c.commit(); 

def GenerateSQL(substrSize): 
    subqueries = ["select substr(content,%i,%i) AS substr, count(*) AS myCount from myTable where length(substr(content,%i,%i))=%i group by substr(content,%i,%i) " % (i,substrSize,i,substrSize,substrSize,i,substrSize) for i in range(50)] 
    sql = 'select substr FROM \n\t(' + '\n\tunion all '.join(subqueries) + ') \nGROUP BY substr HAVING sum(myCount) > 1' 
    return sql 

print GenerateSQL(3) 

print c.execute(GenerateSQL(3)).fetchall() 

Die Abfrage erzeugt sieht aus wie:

select substr FROM 
    (select substr(content,0,3) AS substr, count(*) AS myCount from myTable where length(substr(content,0,3))=3 group by substr(content,0,3) 
    union all select substr(content,1,3) AS substr, count(*) AS myCount from myTable where length(substr(content,1,3))=3 group by substr(content,1,3) 
    union all select substr(content,2,3) AS substr, count(*) AS myCount from myTable where length(substr(content,2,3))=3 group by substr(content,2,3) 
    union all select substr(content,3,3) AS substr, count(*) AS myCount from myTable where length(substr(content,3,3))=3 group by substr(content,3,3) 
    union all select substr(content,4,3) AS substr, count(*) AS myCount from myTable where length(substr(content,4,3))=3 group by substr(content,4,3) 
    ...) 
GROUP BY substr HAVING sum(myCount) > 1 

Und die Ergebnisse es sind produziert:

[(u'app',), (u'ati',), (u'ion',), (u'nat',), (u'pin',), (u'ple',), (u'ppl',), (u'tio',)] 
+0

Ich werde das versuchen und Sie wissen lassen, ob mein Server explodiert;) Thx – Digits

2

Es tut mir leid, wie ich habe nicht Ich habe eine Weile mit php gespielt & Ich habe keine richtige Testumgebung dafür, aber ich habe schnell einen Weg gefunden, dies in C# 3.5

zu tun

Pseudocode: Erstellen Sie eine Tabelle mit Strings der angegebenen Länge & eine Anzahl von Vorkommen daneben. Wählen Sie die Anzahl> 1:

static void Main(string[] args) 
    { 

     string[] data = { "apple", "pinapple", "application", "nation" }; 
     string[] result = my_func(3,data); 

     foreach (string str in result) 
     { 
      Console.WriteLine(str); 
     } 
     Console.ReadKey(); 
    } 

    private static string[] my_func(int l, string[] data) 
    { 
     Dictionary<string,int> dict = new Dictionary<string,int>(); 
     foreach (string str in data) 
     { 
      for (int i = 0; i < str.Length - l + 1; i++) 
      { 
       string part = str.Substring(i, l); 
       if (dict.ContainsKey(part)) 
       { 
        dict[part]++; 
       }else { 
        dict.Add(part,1); 
       } 
      } 
     } 
     var result = from k in dict.Keys 
       where dict[k] > 1 
       orderby dict[k] descending 
       select k; 

     return result.ToArray<string>(); 
    } 
+0

Das sieht interessant aus. Ich bin nur ein wenig besorgt über die Leistung, da alle "schnelle Anrufe" Sie zu Ihrem Wörterbuch machen, die in meinem Fall SQL-Abfragen sein wird. Und einen Tisch mit 10k-Records zu cachen, ist vielleicht auch keine gute Idee, aber ich werde es überprüfen! – Digits

+0

Sie haben Recht, dieser Code sollte auf dem Server laufen, dann scheint es, dass er in SQL geschrieben werden muss, aber dann müssten Sie in SQL iterieren, was praktisch unmöglich ist. Ich mag eigentlich Gregs Antwort, nur dass die erzeugte SQL-Abfrage wahnsinnig ist und von der Feldlänge abhängt. –