2

我想在表中存储一个附加列作为“排序值”,它是标题列的数字表示,这样这些值的顺序就代表了字符串的自然字母排序顺序。即,这样我就可以检索按排序值排序的行,它们将按自然排序顺序 - 当我插入新行时,我可以生成数值并知道相对于其他值的值将代表字符串的位置在字母搜索中,精确到前 X 个字母左右。

这有几个原因:首先,我想要一个比数据库服务器提供的简单排序更自然的排序,其中“The”和“A”之类的东西和标点符号在开始时会被忽略,而数字会被“自然”处理'。

其次,这适用于具有大量排列的索引 - 它会节省空间,并且可能会在遍历具有许多行的索引时节省时间。

我所追求的是将字符串转换为该数值的算法,或者我想只是一个规范化的字符串值。

我正在使用 PHP 和 MySQL。

恐怕“从数据库中提取所有内容并使用 natcasesort() 在 PHP 中排序”不是这种特殊情况的解决方案,因为我想在它们之前按排序顺序检索行(使用 order by 和 group by)得到一个连接或限制子句。谢谢。

编辑:

感谢您到目前为止的回答。我突然想到,我的应用程序使用 UTF-8 的事实非常相关。话虽如此,我认为以压缩/数字形式表示字符串的初始部分的实用性是一种延伸,可能只是某种规范化形式(所有大小写折叠,数字零填充,以及尽可能多的字符)归一化到它们的根,即 ã 到 a) 是合适的。

4

2 回答 2

1

精确到前 X 个字母左右”部分至关重要,因为不可能完全准确地分配数字。要看到这一点,假设您的title列是具体的varchar(50)并且您想要使用 32 位列integer sort_order。然后您可以存储 (255^51 - 1) 个不同的标题,每个标题都需要不同的sort_order值——但只有 2^32 个不同的sort_order值可供使用。即使您说您永远不会添加超过 2^32 行,您也需要提前知道他们将拥有哪些标题,以便提出一个避免sort_order每次插入行时都必须重新分配所有值的方案。

尽管“理论上完美”的解决方案是不可能的,但仍然有可能获得一个实用的“近似”系统,该系统应该以完美的精度处理多达数百万行。最简单的方法是使用浮点类型。最初,按排序顺序列出行并将第一行的sort_order值分配为 1.0,将第二行的值分配为 2.0,依此类推。然后,每当插入一行时,将其设置sort_order为排序顺序两边各行的中点(即平均值)。如果新添加的行位于所有现有行之前(或之后),只需将其设置为小于(或大于)之前的最小(或最大值)sort_order值 1。

从头开始重新分配数字(如在初始构建步骤中)以定期或在大量更新后“平滑”值是一个好主意。特别是如果表格从小开始变大,您可能会在末端发现一些“一堆”数字。

于 2009-02-26T16:49:52.280 回答
1

感谢您到目前为止的答案。我只是想用我要使用的解决方案来更新人们。我采取的方法与我在问题中设想的方法不同。

回顾一下,我想存储字符串的表示形式,这样当以二进制顺序检索时,我为“8 Mile”存储的任何内容都将在我为“101 Dalmations”存储的任何内容之前排序。

对于字符串中的每个数字(本质上是一个数字序列),我在它们之前插入一个数字,描述该数字的位数。

所以,“8”变成“18”,“101”变成“3101”。它为数字添加了一些冗余,因为您使用的数字比您需要的多,并且某些值不存在,但它们现在具有二进制排序将数字排序为数字顺序的属性。“101”会事先排在“8”之前,这是不希望的。添加额外的数字后,“18”排在“3101”之前。

注意:如果数字是 9 位或更多位,我会在开头添加两个数字:数字中的位数减去 9,然后是 9,然后是数字。这允许最多 18 位数字:对我来说已经足够了。

我也在以其他方式对字符串进行规范化——所有内容都小写,Unicode 字符将被翻译成最接近的 ascii 等价字符,如果它们是第一个单词,'a'、'an' 和 'the' 将被删除.

我放弃了将字符串变成一个大数值;它仍然是一个字符串,只是它不是为人类阅读而设计的。

于 2009-03-12T02:28:30.110 回答