4

我已经搜索了几天以在 mysql 中将字符串排序为数字。

我的行看起来像这样:

订单列

1.1.2
1.1.100
1.1.1

在 mysql 中按此列升序排序将产生:

1.1.1
1.1.100
1.1.2

我有兴趣获得以下结果:

1.1.1
1.1.2
1.1.100

有没有办法使用 SQL 产生这个结果?

我的专栏的其他可能值:

28.1999.1.1
1
1.1.154.20
100.1.1.1.1.15

谢谢,我感谢大家的时间。

编辑: 存储树数据的快速关系方法(例如文章的线程评论) 看看第一个答案,Ayman Hourieh 的答案。我正在尝试使该解决方案发挥作用。我的网站每篇文章的评论不超过 10k,所以我找到了这样的解决方法:

000001
000002
000002.000001
000002.000001.000001
000002.000002
000002.000003
000003

基本上,将零放在我的评论计数器之前,这样字符串比较就不会失败。但这仅适用于 99999 条评论。我可以添加更多的零,比如说 10 个零,这将适用于 999999999 条评论,但我希望有一个更优雅的解决方案。

4

10 回答 10

4

如果字符串不是太长,你可以这样做

ORDER BY cast(replace(your_column_name,'.','') as unsigned);
于 2012-12-18T13:53:13.417 回答
2

您将无法有效地执行此操作,因为这会错过所有索引,但如果它是一次性的,这将起作用。遗憾的是,由于 MySQL 无法一次替换多个字符(据我所知),它看起来很糟糕。

SELECT value FROM TEST ORDER BY 
   REPLACE(
    REPLACE(
      REPLACE(
        REPLACE(
          REPLACE(
            REPLACE(
              REPLACE(
                REPLACE(
                  REPLACE(value, 
                    '1', '0'),
                  '2', '0'), 
                '3', '0'), 
              '4', '0'), 
            '5', '0'), 
          '6', '0'), 
        '7', '0'), 
      '8', '0'), 
    '9', '0'),value;

它基本上会用 0 替换所有数字并首先按该顺序排序。由于.在 0 之前排序,它将正确地按数字组排序。完成后,只需按值排序,因为具有相同数字组的任何值都应按正确顺序排序。

为了提高效率,您可以将替换的值作为列存储在数据库中,以便对其进行索引。

SQLfiddle 演示在这里

于 2012-12-18T15:04:51.333 回答
1
SELECT INET_ATON('10.0.5.9');

试试你的这个功能:)

也许这不是替代方案,因为它仅适用于 IP 地址类型。而且您确实拥有比 IP 地址更多的部分。

于 2012-12-18T14:01:06.773 回答
1

这不会很有效并且可以清理,但这是如何做到这一点的一个想法。它依赖于一个名为 integers 的表,该表有一个名为 i 的列,其中包含 10 行,值为 0 到 9。

SELECT somefield    , SUM(POW(100, occurrences - anInteger) * somefield_split) OrderField
FROM
    (SELECT id,anInteger,  somefield, SUBSTRING_INDEX(SUBSTRING_INDEX(somefield, ".", anInteger), ".", -1) AS somefield_split, LENGTH(somefield) - LENGTH(REPLACE(somefield, '.', '')) + 1 AS occurrences
    FROM splittertest, (SELECT a.i*10+b.i AS anInteger FROM integers a, integers b) Sub1
    HAVING occurrences >= anInteger) Sub2
GROUP BY somefield
ORDER BY somefield, OrderField

想法是子选择获取从 0 到 99 的数字范围,并基于此将字符串从点分隔值中拆分出来。它获取特定字符串中的点数。然后,它将字符串的每个位乘以 100 的部分总数减去该部分的数量的幂,并在此基础上求和。

所以 5.10.15 分为 5、10 和 15。有 3 个部分,所以第一个部分乘以 100 的 (3 - 0) 次方,第二个部分乘以 100 的 (2 - 0) 次方,等等.

如果点数不同(即点数越多的点总是越大),这确实会产生奇怪的结果,但这可以通过在计算功率时使用任何线上的最大点数而不是数字来解决在那条特定线上的点。

祝你好运!

于 2012-12-18T14:38:14.807 回答
0

如果您按最后一位数字组排序,那么

SELECT CAST(MID(order_column, 
CHAR_LENGTH(order_column) - 
LOCATE('.',REVERSE(order_column))+2) AS DECIMAL) AS order_column_as_number
FROM thetable 
ORDER BY order_column_as_number

似乎工作。

如果有没有 '.' 的字符串,则根本不起作用 在它们中,如果您还想按其他组订购,则必须提取更多零件进行订购,但如果您真的希望仅在 sql 中完成,这可能是一个开始。

于 2012-12-18T14:03:13.453 回答
0

确保这些数字的列INT不是 varchar。

如果您使用 varchar 您的列将按第一个有 1 的人排序,依此类推...

于 2012-12-18T14:06:08.153 回答
0

你可以使用下面的sql

SELECT REPLACE(column_name,'.','') AS column_name1 FROM table_name ORDER BY column_name1;
于 2012-12-18T14:00:04.353 回答
0

创建一个与此列相等的新列,字符串替换为“。” 用''(什么都没有)。将此新字段存储为数字。在您的查询中按此字段排序。

如果您无法向表中添加新列,您可以在 PHP 等中处理此列,以达到相同的效果,例如在网站上显示。

http://php.net/manual/en/function.str-replace.php
于 2012-12-18T13:51:34.347 回答
0

这是我对最多 4 位小数的数字的解决方案:

SELECT myCol, SUBSTRING_INDEX(myCol, ',', 1) * 10000 + LEFT(CONCAT(SUBSTRING_INDEX(myCol, ',', -1), '0000'), 4) as toOrder 
FROM `myTable`
ORDER BY toOrder DESC

您可以这样设置 8 位小数:

SELECT myCol, SUBSTRING_INDEX(myCol, ',', 1) * 100000000 + LEFT(CONCAT(SUBSTRING_INDEX(myCol, ',', -1), '00000000'), 8) as toOrder 
FROM `myTable`
ORDER BY toOrder DESC

ETC...

于 2019-05-21T13:55:34.107 回答
0

首先按INSTR排序,然后通过替换“。”进行排序。

SELECT content_id FROM TEST ORDER BY INSTR(`content_id`, '.'), replace(`content_id`,'.','')

SQLfiddle

于 2020-08-03T02:23:04.437 回答