我正在开发一款账簿应用程序。我的主要问题是我的客户有一个类似于这样的会计科目代码:
1.1.1,
1.1.2
......
1.1.10,
1.1.11,
.........
使用 PHP 或 MySQL,我只能将它们排序到
1.1.1,
1.1.10,
1.1.11,
1.1.2,
.......
任何关于如何排序,使得1.1.10在1.1.9之后的帮助都将不胜感激。提前致谢。
我正在开发一款账簿应用程序。我的主要问题是我的客户有一个类似于这样的会计科目代码:
1.1.1,
1.1.2
......
1.1.10,
1.1.11,
.........
使用 PHP 或 MySQL,我只能将它们排序到
1.1.1,
1.1.10,
1.1.11,
1.1.2,
.......
这不太美观,但它可以工作:
ORDER
BY SUBSTRING_INDEX(CONCAT( col ,'.'),'.',1) + 0
, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT( col ,'.'),'.',2),'.',-1) + 0
, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT( col ,'.'),'.',3),'.',-1) + 0
, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT( col ,'.'),'.',4),'.',-1) + 0
, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT( col ,'.'),'.',5),'.',-1) + 0
, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT( col ,'.'),'.',6),'.',-1) + 0
, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT( col ,'.'),'.',7),'.',-1) + 0
为了测试这些表达式,你可以在SELECT语句中使用它们,并验证它们提取了正确的组件,并且它们被正确排序:
SELECT col
, SUBSTRING_INDEX(CONCAT( col ,'.'),'.',1) + 0 AS p1
, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT( col ,'.'),'.',2),'.',-1) + 0 AS p2
, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT( col ,'.'),'.',3),'.',-1) + 0 AS p3
, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT( col ,'.'),'.',4),'.',-1) + 0 AS p4
, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT( col ,'.'),'.',5),'.',-1) + 0 AS p5
, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT( col ,'.'),'.',6),'.',-1) + 0 AS p6
, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT( col ,'.'),'.',7),'.',-1) + 0 AS p7
FROM mytable
ORDER BY 2,3,4,5,6,7,8
不必解释其原理,我将着重介绍一些重要的“技巧”
在列末尾添加一个“.”,这样可以避免多次返回最后一个位置
使用SUBSTRING_INDEX来检索直到第n个“.”的部分
使用SUBSTRING_INDEX来检索该部分的尾随部分(从后往前读,到达首个点)
添加零,将字符串转换为数字值
CONCAT
到col
的末尾。内部的SUBSTRING_INDEX
将获取到第X个小数点之前(不包括该小数点)的子字符串,而外部的SUBSTRING_INDEX
将返回从右边开始计数的第一个小数点右侧(不包括该小数点)的所有内容。这应该只会给你一个数字值。所以我不明白在连接小数时的意义所在。 - Cave JohnsonSUBSTRING_INDEX
有些古怪。举个例子, SELECT SUBSTRING_INDEX(SUBSTRING_INDEX('1.2','.',4),'.',-1)
返回值为 2
。(将 4 替换为任意大于等于 2 的整数,结果也是 2
)。如果我们连接一个尾随的点字符 1.2.
,那么我们将得到一个空字符串。我考虑按照不同数量点排序的情况,并希望 1.3
排在 1.3.1
之前。如果 1.3
没有额外的点,则 ORDER BY 表达式将评估为“1”,“3”,“3”,“3”,“3” ... 这将导致 1.3
在 1.3.1
之后排序。 - spencer7593'1.3.'
,order by表达式返回'1','3','0','0','0'。这就是我想要的:当这些组件缺失时,返回p3、p4、p5等零。这可能并不是严格必要的。但在一般情况下...当我们想要排序'3'和'3.1.4.2'时...我希望将3处理为3.0.0.0
。通过运行SELECT来查看它的实际效果。(我的解决方案更通用,适用于不仅仅是OP案例中的示例,具有完全相同数量的点。OP在另一个答案的后续评论中有更多的点。) - spencer7593将值分配给数组并使用natsort()自然地排序。
$foo = array ('1.1.1', '1.1.2', '1.1.10', '1.1.11');
natsort ($foo);
print_r ($foo);
/*
Array
(
[0] => 1.1.1
[1] => 1.1.2
[2] => 1.1.10
[3] => 1.1.11
)
*/
?>
你需要提取小数点之间的数字并将它们视为数字。使用SUBSTRING_INDEX
函数提取数字,再使用CAST
函数将其转换为数字类型:
SELECT *
FROM myAccounts
ORDER BY
CAST(SUBSTRING_INDEX(account_number, '.', 1) AS UNSIGNED),
CAST(SUBSTRING_INDEX(account_number, '.', -2) AS UNSIGNED),
CAST(SUBSTRING_INDEX(account_number, '.', -1) AS UNSIGNED)
SELECT col FROM mytable ORDER BY REPLACE(col, ".", "")+0
REPLACE
去除 .
并且 MySQL 会自动使用数学运算转换字符串。您可以尝试使用 REPLACE(col, ".", "")*1
name
,则使用以下的ORDER BY
子句。ORDER BY length(name), name
我曾经遇到过类似的问题,我是这样解决的:
SELECT .... , CAST(SUBSTRING([column_name],1) AS UNSIGNED) AS myNum, CAST(SUBSTRING([column_name],3) AS UNSIGNED) AS myDec
FROM ...
WHERE ...
ORDER BY myNum, myDec
在你的情况下,也许你需要更深入的了解。
希望这能帮助你获得一些见解。