MySQL, выберите записи, содержащие не менее X символов - PullRequest
3 голосов
/ 19 июля 2009

Я пытаюсь сделать следующее. Допустим, у нас есть таблица, которая содержит эти поля (ID, содержимое)

1 | яблоко

2 | ананаса

3 | применение

4 | страна

Теперь я ищу функцию, которая сообщит мне все возможные общие совпадения. Например, если аргумент равен «3», функция возвратит все возможные строки из 3 символов, которые встречаются в более чем одной записи.

В этом случае я получаю «app», «ppl», «ple», «ati», «tio», «ion»

Если аргумент равен "4", я получаю: "appl", "pple", "atio", "tion "

Если arugment равен «5», я получаю: «apple», «ation»

Если аргумент равен "6", ничего не возвращается.

До сих пор я не нашел функцию, которая выполняет это.

Thx!

Некоторая дополнительная информация: Я использую это в сценарии PHP с базой данных MySQL. Я действительно просто хочу указать количество символов в качестве аргумента и, конечно, таблицу для поиска.

Ответы [ 3 ]

3 голосов
/ 20 июля 2009

Ну, это уродливо, но работает нормально. Это универсальный SQL и будет работать в любой среде. Просто сгенерируйте количество выборок подстроки, которая превышает максимальную длину поля, которое вы читаете. Измените число 50 в функции на число, которое превышает длину вашего поля. Он может вернуть действительно длинный запрос, но, как я уже сказал, он будет работать нормально. Вот пример в 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()

Сгенерированный запрос выглядит так:

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

И результаты, которые он выдает:

[(u'app',), (u'ati',), (u'ion',), (u'nat',), (u'pin',), (u'ple',), (u'ppl',), (u'tio',)]
2 голосов
/ 20 июля 2009

Извините, я некоторое время не играл с php, и у меня нет подходящей тестовой среды, но я быстро разработал способ сделать это в c # 3.5

псевдокод: создайте таблицу со строками указанной длины и числом событий рядом с ней. Выберите где считать> 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 голосов
/ 19 июля 2009

Одним из очевидных вариантов является использование REGEX. У меня нет предыдущего опыта в этом, но это может помочь вам: http://dev.mysql.com/doc/refman/5.1/en/regexp.html

Вам нужно найти подходящее выражение, соответствующее вашему.

...