C# 如何对忽略项目(“the”、“a”等)的SQLite查询进行排序?

C# 如何对忽略项目(“the”、“a”等)的SQLite查询进行排序?,c#,sqlite,stop-words,C#,Sqlite,Stop Words,我正在使用C#显示我从SQLite数据库调用的电影标题列表。目前,我正在使用一个自定义的ListBox类,它有一个函数来对文本进行排序,从每个项目的开头去掉单词“the”。然而,这似乎不是最简单的方法,因为它从SQLite数据库调用,然后进行排序。我更愿意把它简化为一个步骤,希望在我的“选择”查询中直接从数据库排序 我对此做了一些搜索,并找到了一些建议,包括在数据库中创建一个额外的排序方式列。虽然这当然是可能的,但我想知道是否有更简单的选项不需要插入几乎相同的重复信息(特别是当数据库变得更大时)

我正在使用C#显示我从SQLite数据库调用的电影标题列表。目前,我正在使用一个自定义的ListBox类,它有一个函数来对文本进行排序,从每个项目的开头去掉单词“the”。然而,这似乎不是最简单的方法,因为它从SQLite数据库调用,然后进行排序。我更愿意把它简化为一个步骤,希望在我的“选择”查询中直接从数据库排序

我对此做了一些搜索,并找到了一些建议,包括在数据库中创建一个额外的排序方式列。虽然这当然是可能的,但我想知道是否有更简单的选项不需要插入几乎相同的重复信息(特别是当数据库变得更大时)。我对SQLite非常陌生,但我读过一些关于创建可用于创建自定义排序的collate函数的内容。但是,我不确定这是否适用于它,并且似乎找不到在C#中实现它的任何帮助


希望有人能分享一些指导。如果一个额外的排序列是最好的方式,那么这就是我应该做的。

为了避免插入重复数据,有两列如何:TITLE\u前缀(通常为空,但有时包含“the”或“A”;此列上没有索引)和TITLE(包含没有“the”或“A”的标题;这是创建索引的列)。要显示数据,必须将TITLE\u前缀和TITLE组合在一起。但您只需搜索标题。

您可以将每个标题存储在两个部分中:
标题
前缀

使用SQLite,您可以通过
| |运算符
组合2个字符串值,也称为
串联运算符

下面是一个例子:

SELECT prefix || ' ' || title FROM movies ORDER BY title
如果前缀为空,您也可以使用
ltrim
,这样前面就没有空格了:

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

另一种选择是将前缀存储在标题的末尾。例如,在许多电影商店中,您会看到如下内容:

三个火枪手

在C#代码中

如果您想在C#中执行此操作,请使用LINQ为您进行排序。我发了一封信。这将允许您:

  • 避免复制数据库中的数据
  • 无论使用哪种RDBMS,都可以像平常一样利用DB索引
  • 在配置文件中输入噪声字,从而在修改列表时减少停机时间/重建/重新部署
  • 确保解决方案在客户端代码中更具可读性
在您的SQLite语句中

简单地按顺序用空格替换干扰词怎么样?这是一个丑陋的第一步,但是强烈地考虑一个新的列来存储这个值以进行排序。

ORDER BY REPLACE(REPLACE([title],'the',''), 'a', '')
诚然,当你以这样的方式结束时,这会变得丑陋:

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

您可以尝试构建一个支持标题全文搜索的表(使用模块)。然后你就可以快速搜索标题中的任何单词,而不需要你做很多额外的工作。例如,用户查询good-bad-sugger可能会产生“The good,The bad and-sugger”作为其第一个结果之一。这一切的额外成本通常是文本本身长度的四分之一,但对于您的数据集来说可能更高,因为标题不是完整的英文文本。您还需要花时间构建这些额外的索引——您不想在实时系统的主数据集上构建它们(显然)——但这应该不是一个太大的问题。

创建一个虚拟列(可以用C实现的函数的结果)并在此虚拟列上排序。该函数可以像“三个火枪手”中那样将“The”移到末尾,或丢弃“The”,无论您想做什么。

以下是解决方案:

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)

这将不允许数据库在
title
上使用索引(如果存在)。看起来OP需要很多数据。@Daniel:事实上,你在索引上是对的。对于高性能,OP可能希望找到SQLite之外的另一个DB。C#解决方案更具吸引力。排序实际上属于客户机,不管RDBMS是什么。@downvoter:请解释一下为什么使用LINQ排序没有帮助?建议使用一个新列来存储“排序”值如何?这些建议是如何获得否决票的?使用replace()函数不起作用,尤其是使用“a”。您将用零替换所有字母a。意思是“苹果”变成了“苹果”,可能不是你想要的。System.Data.SQLite网站上有关于如何做到这一点的文档。排序将在SQLite中的SELECT语句中完成,尽管您将放弃对排序索引的访问。如果你现在将标题放在列表框中,我假设你的结果集中没有成千上万的标题,所以这应该没有问题。下面是一个例子,说明我的意思:不要忘记你的用户可能使用的语言不是英语。
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)