2009-07-19 7 views
3

J'essaie d'accomplir ce qui suit. Disons que nous avons une table qui contient ces champs (ID, contenu)MySQL, sélectionnez les enregistrements avec au moins X caractères correspondants

1 | pomme

2 | ananas

3 | application

4 | Maintenant, je cherche une fonction qui me dira toutes les correspondances communes possibles. Par exemple, si l'argument est "3", la fonction renvoie toutes les chaînes possibles à partir de 3 caractères qui apparaissent dans plus d'un enregistrement.

Dans ce cas, je reçois "app", "ppl", "PLE", "ati", "tio", "ion"

Si l'argument est "4", je reçois: « Appl », "pple", "ATIO", "tion"

Si le arugment est "5", je reçois: "pomme", "ation"

Si l'argument est "6", nohting est retourné .

Jusqu'à maintenant, je n'ai pas trouvé de fonction qui accomplit cela.

Thx!

Quelques informations supplémentaires: J'utilise ceci dans un script PHP avec une base de données MySQL. Je veux juste donner la quantité de caractères comme argument et bien sûr la table à chercher.

+0

quoi d'autre prévoyez-vous d'envoyer en tant qu'argument à la requête en plus du nombre représentant la longueur? De quel langage de codage sera-t-il basé? –

Répondre

0

Une option évidente est d'utiliser REGEX. Je n'ai aucune expérience antérieure dans ceci mais ceci pourrait vous être utile: http://dev.mysql.com/doc/refman/5.1/en/regexp.html

Vous devrez trouver une expression appropriée pour correspondre à ce dont vous avez besoin.

+0

Ce n'est pas très évident .. Nous parlons d'exécuter une regex aléatoire et de faire correspondre le résultat avec tous les autres enregistrements de la table. Je ne peux pas voir de SQL impliquant regex pour cela. – PatrikAkerstrand

+0

Comme indiqué ci-dessus, ce n'est qu'une petite partie de la solution. Je ne connais pas les personnages à rechercher. Avec 5 caractères, cela donne 2^5 requêtes regexp que je devrais exécuter si je le faisais aléatoirement. Malheureusement, ce n'est pas adapté à ce problème. – Digits

+0

@Machine Je suppose que je n'ai pas complètement compris la question avant de la relire. D'accord, mon option «évidente» n'était pas applicable après tout. Je ne pense vraiment pas que cela peut être réalisé en utilisant seulement des requêtes SQL, mais je voudrais certainement avoir tort. –

3

Eh bien, c'est un peu moche, mais ça marche très bien. C'est SQL générique et fonctionnera dans n'importe quel environnement. Générez simplement un nombre de sélections d'une sous-chaîne supérieure à la longueur maximale du champ que vous lisez. Changez le nombre 50 dans la fonction à un nombre qui dépasse votre longueur de champ. Il peut retourner une requête vraiment longue, mais comme je l'ai dit, ça va fonctionner correctement. Voici un exemple en 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() 

La requête générée ressemble:

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 

Et les résultats qu'il produit sont:

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

Je vais essayer cela et vous faire savoir si mon serveur explose;) Thx – Digits

2

Je suis désolé que je n'ai pas joué avec php pendant un certain temps & Je n'ai pas un environnement de test approprié pour cela, mais j'ai rapidement mis au point une façon de le faire en C# 3.5

pseudocode: construire une table avec des chaînes de la longueur spécifiée & nombre d'occurrences à côté de lui. Sélectionnez où compte> 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

Cela semble intéressant. Je suis juste un peu inquiet au sujet de la performance, puisque tous les "appels rapides" que vous faites à votre dictionnaire, qui dans mon cas seront des requêtes sql. Et mettre en cache une table avec des enregistrements 10k n'est peut-être pas une bonne idée non plus, mais je vais vérifier! – Digits

+0

Vous avez raison, ce code devrait tourner sur le serveur, alors il semble qu'il doit être écrit en SQL, mais alors vous auriez besoin d'itérer en SQL, ce qui est pratiquement impossible. J'aime vraiment la réponse de Greg, sauf que la requête SQL générée semble fou et cela dépend de la longueur du champ. –

Questions connexes