Как я могу отсортировать SQLite-запрос, игнорируя статьи ("the", "a" и т. Д.)? - PullRequest
11 голосов
/ 12 сентября 2010

Я использую C # для отображения списка названий фильмов, которые я вызываю из базы данных SQLite.В настоящее время я использую пользовательский класс ListBox, который имеет функцию для сортировки текста, убирая слово «The» в начале каждого элемента.Тем не менее, это не совсем простой способ сделать это, поскольку он вызывает из базы данных SQLite и сортирует затем .Я бы предпочел сократить его до одного шага, надеюсь, сортируя прямо из базы данных в моем запросе «SELECT».

Я провел поиск по этому вопросу и нашел несколько предложений, в том числе созданиедополнительная сортировка по столбцу в базе данных.Хотя это, безусловно, возможно, мне интересно, есть ли более простые варианты, которые не требуют вставки практически идентичной дублирующейся информации (особенно, если база данных становится больше).Я довольно новичок в SQLite, но я кое-что прочитал о создании функции сортировки, которую можно использовать для создания пользовательских порядков.Однако я не уверен, подходит ли это для него, и, похоже, не могу найти никакой помощи в его реализации на C #.

Я надеялся, что кто-то сможет поделиться некоторыми рекомендациями.Если лучше всего использовать дополнительный столбец сортировки, то это то, что я буду делать.

Ответы [ 6 ]

6 голосов
/ 12 сентября 2010

Чтобы избежать вставки дублирующих данных, как насчет двух столбцов: TITLE_PREFIX (обычно пустой, но иногда содержит «The» или «A»; нет индекса для этого столбца) и TITLE (содержит заголовок без «The» или « "; Это столбец, по которому вы создаете индекс). Чтобы отобразить данные, вы должны объединить TITLE_PREFIX и TITLE. Но вы просто ищете по названию.

4 голосов
/ 02 марта 2013

Вот решение:

ORDER BY (CASE 
    WHEN sortTitle LIKE 'the %' THEN substr(sortTitle,5) 
    WHEN sortTitle LIKE 'a %' THEN substr(sortTitle,3) 
    WHEN sortTitle LIKE 'an %' THEN substr(sortTitle,4) 
    ELSE sortTitle END)
1 голос
/ 12 сентября 2010

Вы можете хранить каждый заголовок в 2 частях: title и prefix.

С SQLite вы можете комбинировать 2 строковых значения через || operator, также известный как concatenate operator.

Вот пример:

SELECT prefix || ' ' || title FROM movies ORDER BY title

Вы также можете использовать ltrim, если префикс пуст, и у вас нет пробела спереди:

SELECT ltrim(prefix || ' ' || title) FROM movies ORDER BY title

Другая альтернатива - хранить префикс в конце заголовка.Например, во многих магазинах фильмов вы увидите что-то вроде:

Три мушкетера,

0 голосов
/ 14 сентября 2010

Создание виртуального столбца (результат функции, которая может быть реализована в C #) и сортировка по этому виртуальному столбцу. Функция может сдвинуть «The» в конец, как в «Three Musketeers, The», или отменить «The», как вам угодно.

0 голосов
/ 13 сентября 2010

Вы можете попытаться создать таблицу, которая поддерживает полнотекстовый поиск (используя модуль FTS ) для заголовка. Тогда вы сможете выполнять быстрый поиск по любым словам в названии, не требуя много дополнительной работы с вашей стороны. Например, пользовательский запрос good bad ugly может привести к «Хорошему, Плохому и Уродливому» в качестве одного из первых результатов. Дополнительная стоимость всего этого составляет около четверти длины самого текста в целом, но может быть больше для вашего набора данных, так как заголовки не являются полным английским текстом. Вам также нужно потратить время на создание этих дополнительных индексов - вы не хотите строить их на своем основном наборе данных в реальной системе (очевидно) - но это не должно быть слишком большой проблемой.

0 голосов
/ 12 сентября 2010

в коде C #

Если вы хотите сделать это в C #, используйте LINQ, чтобы сделать заказ за вас. Я разместил полный образец на PasteBin . Это позволит вам:

  • избегайте дублирования данных в вашей базе данных
  • используйте индексы БД, как обычно, независимо от того, какая СУБД
  • вставляет шумовые слова в файл конфигурации, тем самым сокращая время простоя / перестроение / повторное развертывание при изменении списка
  • гарантирует, что решение будет более читабельным в коде вашего клиента
DropDownList1.DataSource = myBooks.OrderBy(n => ReplaceNoise(n.Title))

public string ReplaceNoise(string input)
{
     string[] noise = new string[] { "the", "an", "a" };

     //surely this could be LINQ'd 
     foreach (string n in noise)
     {
         if (input.ToLower().StartsWith(n))
         {
             return input.Substring(n.Length).Trim();
         }
     }
     return input;
}

в вашем выражении SQLite

Как насчет простой замены слов с шумом пробелами в порядке? Это ужасный первый шаг, но мы настоятельно рекомендуем создать новый столбец для хранения этого значения в целях сортировки.

ORDER BY REPLACE(REPLACE([title],'the',''), 'a', '')

По общему признанию, это становится уродливым, когда вы в конечном итоге с этим:

REPLACE(REPLACE(REPLACE(REPLACE([title],'The ',''),'a',''),'of',''),'by','')
...