SQL订单字符串作为数字


137

我将数字保存VARCHAR到MySQL数据库。INT由于某些其他情况,我无法制作它们。

排序时将它们当作字符而不是数字。

在数据库中我有

1 2 3 4 5 6 7 8 9 10...

在我的页面上,它显示如下排序列表:

1 10 2 3 4 5 6 7 8 9

如何使它按数字升序显示?


5
当然,您应该将数据存储为数字而不是字符串。
2012年

@Oded您可以具有一些任意数据(例如,设置),仅在非常特殊的情况下才希望通过其数值进行排序。
Glutexo

非常有趣的文章-适用于MSSQL,但适用于MySQL则相对类似:essentialsql.com/use-sql-server-to-sort-alphanumeric-values
AquaAlex

Answers:


256

如果可能,则无论如何仅存储数字,应将列的数据类型更改为数字。

如果您不能这样做,则将列值integer 强制转换

select col from yourtable
order by cast(col as unsigned)

隐式地使用例如数学运算来强制转换为数字

select col from yourtable
order by col + 0

BTW MySQL将字符串从左到右转换。例子:

string value  |  integer value after conversion
--------------+--------------------------------
'1'           |  1
'ABC'         |  0   /* the string does not contain a number, so the result is 0 */
'123miles'    |  123 
'$123'        |  0   /* the left side of the string does not start with a number */

3
按col * 1排序很完美。这背后的魔力是什么?抱歉,我不是专业人士,所以这可能是一个愚蠢的问题,但是* 1如何使其变为数字?
Jamol 2012年

12
MySQL自动将字符串转换为数字以与1
juergen d 2012年

1
第一个选项是最合适的,第二个选项有一个额外的步骤,但它的工作量仍然很少。
Manatax

5
如果您混合使用了字符串和数字,并且希望两者都进行排序,请使用“ order by col * 1,col”
Hayden Thring 2015年

1
@superphonic:结果将为decimal
juergen d 2016年

70

另一种方法,不使用单个强制转换。

(对于使用JPA 2.0的人,不允许强制转换)

select col from yourtable
order by length(col),col

编辑:仅适用于正整数


9
这是一个很好的方法,可以使用同时包含int和string的列
Sruit A.Suk 2015年

1
这并非在所有情况下都有效。从头顶上看,无效的案例是整数的混合;负数,带前导零的数字,带分数的数字以及单词和数字的组合。
WonderWorker

3
无需任何铸造和杂耍类型的绝佳解决方案,+ 1
Maksim Luzik

乍一看似乎没什么用,但它能用!谢谢!
try2fly.b4ucry19年


17

我要排序的列具有字母和数字的任意组合,因此我以本文中的建议为起点,并提出了建议。

DECLARE @tmp TABLE (ID VARCHAR(50));
INSERT INTO @tmp VALUES ('XYZ300');
INSERT INTO @tmp VALUES ('XYZ1002');
INSERT INTO @tmp VALUES ('106');
INSERT INTO @tmp VALUES ('206');
INSERT INTO @tmp VALUES ('1002');
INSERT INTO @tmp VALUES ('J206');
INSERT INTO @tmp VALUES ('J1002');

SELECT ID, (CASE WHEN ISNUMERIC(ID) = 1 THEN 0 ELSE 1 END) IsNum
FROM @tmp
ORDER BY IsNum, LEN(ID), ID;

结果

ID
------------------------
106
206
1002
J206
J1002
XYZ300
XYZ1002

希望这可以帮助


您可以简单地使用1 - ISNUMERIC(ID)而不是(CASE WHEN ISNUMERIC(ID) = 1 THEN 0 ELSE 1 END)将0更改为1,反之亦然。
S.Serpooshan


4

另一种转换方式。

如果您有字符串字段,则可以按以下方式对其进行转换或将其数字部分转换:添加前导零以使所有整数字符串具有相同的长度。

ORDER BY CONCAT( REPEAT(  "0", 18 - LENGTH( stringfield ) ) , stringfield ) 

或按字段的一部分排序,例如“ tensymbols13”,“ tensymbols1222”等。

ORDER BY CONCAT( REPEAT(  "0", 18 - LENGTH( LEFT( stringfield , 10 ) ) ) , LEFT( stringfield , 10 ) ) 

2

我也在寻找具有字母前缀的排序字段。这是我找到解决方案的地方。这可能会有助于寻找相同解决方案的人。

栏位值:

FL01,FL02,FL03,FL04,FL05,...FL100,...FL123456789

select SUBSTRING(field,3,9) as field from table order by SUBSTRING(field,3,10)*1 desc

SUBSTRING(field,3,9) 我输入9,因为9足以让我保存最多9位整数值。

因此结果将是123456789 123456788 123456787 ... 100 99 ... 2 1


2

这将处理负数,分数,字符串以及所有内容:

ORDER BY ISNUMERIC(col) DESC, Try_Parse(col AS decimal(10,2)), col;


0

如果您使用的是AdonisJS,并且具有混合ID(例如ABC-202,ABC-201 ...),则可以将原始查询与Query Builder结合使用,并实施上述解决方案(https://stackoverflow.com/a/25061144/4040835)如下:

const sortField =
  'membership_id'
const sortDirection =
  'asc'
const subquery = UserProfile.query()
  .select(
    'user_profiles.id',
    'user_profiles.user_id',
    'user_profiles.membership_id',
    'user_profiles.first_name',
    'user_profiles.middle_name',
    'user_profiles.last_name',
    'user_profiles.mobile_number',
    'countries.citizenship',
    'states.name as state_of_origin',
    'user_profiles.gender',
    'user_profiles.created_at',
    'user_profiles.updated_at'
  )
  .leftJoin(
    'users',
    'user_profiles.user_id',
    'users.id'
  )
  .leftJoin(
    'countries',
    'user_profiles.nationality',
    'countries.id'
  )
  .leftJoin(
    'states',
    'user_profiles.state_of_origin',
    'states.id'
  )
  .orderByRaw(
    `SUBSTRING(:sortField:,3,15)*1 ${sortDirection}`,
    {
      sortField: sortField,
    }
  )
  .paginate(
    page,
    per_page
  )

注: 在这一行:SUBSTRING(:sortField:,3,15)*1 ${sortDirection}

  1. “ 3”代表数字前的最后一个非数字字符的索引号。如果您的混合ID为“ ABC-123”,则您的索引号将为4。
  2. “ 15”用于在连字符后捕获尽可能多的数字。
  3. '1'对子字符串执行数学运算,该运算将子字符串有效地转换为数字。

参考1:您可以在此处阅读更多有关原始查询中的参数绑定的信息:https ://knexjs.org/#Raw-Bindings参考2:Adonis原始查询:https//adonisjs.com/docs/4.1/query-builder# _raw_queries


-3

将您的字段更改为INT而不是VARCHAR。

由于某些其他情况,我无法将它们设为INT。

然后先解决具体情况。否则,您正在解决真正的潜在问题。使用MySQL CAST是一种选择,但它掩盖了您应修正的错误架构。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.