MariaDB的SQL:
SELECT name FROM template_items ORDER BY name ASC;
MariaDB返回以下内容:
3.1 1之2
h1
2.9 1之2
那不是按名称正确排序,为什么?
CREATE TABLE `cms_template_items` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`description` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_520_ci',
`name` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_520_ci',
`url` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_520_ci',
PRIMARY KEY (`id`)
)
COLLATE='utf8mb4_unicode_520_ci'
ENGINE=MyISAM
AUTO_INCREMENT=103;
3.1身体ID 1/2 / 20332E3120426F64792069642031206F662032
h1 / 206831
2.9-body-id-1-of-2 / 322E392D626F64792D69642D312D6F662D32
答案 0 :(得分:1)
请注意前两行的前导空格(十六进制20)。空格在可见字符之前排序;数字在字母前排序。
20 33 ...
20 68 ...
32 2E ...
请参见TRIM
函数(在PHP或MySQL / MariaDB中)。但是您可能应该在插入字符串时而不是在ORDER BY
中调用它。
答案 1 :(得分:0)
通常是用户错误,而在 literally 上可以发现问题,这是设计错误。列类型为VARCHAR
,显然MariaDB太懒了,无法对数字进行排序,仅按字母。
因此,我删除了ORDER BY
子句,并通过PHP处理排序,从而使工作能够胜任:
$items = array();
while ($row1 = mysqli_fetch_assoc($result1))
{
array_push($items,$row1['name']);
}
sort($items);
echo '<pre>'.print_r($items,1).'</pre>';
我遇到了其他一些原因:
ENUM
类型的信息。 (检查您的列类型!)如果有人知道如何强制MariaDB按字母数字顺序对行进行排序,请随时发布有效答案。
答案 2 :(得分:0)
正如您在上面的回答中所说,问题在于VARCHAR
的排序是按字典顺序进行的。它从字面上看每个字符,并且不执行自然排序。
在SQL中解决此问题的一种方法是将name
字段的数字部分与其余部分分开。理想情况下,您需要与此等效的东西:
SELECT name FROM template_items ORDER BY name_numeric, name_alpha ASC;
现在,要获得单独的部分name_numeric
和name_alpha
,您可以执行以下操作:
SELECT name FROM template_items
ORDER BY CONVERT(LEFT(name, REGEXP_INSTR(name, '[[:blank:]]')), DECIMAL(4, 2)),
SUBSTR(name, REGEXP_INSTR(name, '[[:blank:]]'), LENGTH(name)) ASC;
这个想法是先按字符串左侧名称的数字部分进行排序,然后再查看第一个空格右侧的所有其他内容。请注意,数字部分将转换为DECIMAL(4,2)。
具体方法将高度取决于您的数据格式。您可能需要稍微修改正则表达式,并且可能需要更精确的DECIMAL
值。如果需要,您还可以在GROUP BY
中添加其他组。
但是最后,在应用程序层进行排序更容易,并且更加灵活。仅当您的数据模式相对一致时,以上方法才有效。