首页 > 解决方案 > 对包含整数、小数和字符串的字符串字段进行排序 SQL

问题描述

我继承了一个项目,该项目有一个可以包含字符串、小数或整数的表。

我需要对这个字段进行排序。

假设我一次只能(基于 id)抓取一种类型,但可以肯定的是,我仍想在排序之前确认类型,如果不是完全相同的类型,只需按字符串排序。

所以桌子可能看起来像这样。

select id, fkID, myValue from myTable

 id |fkID|myValue
____|____|_______
 1  |14  |abc
 2  |14  |ghi
 3  |14  |def

 4  |11  |2000
 5  |11  |1500
 6  |11  |10000

 7  |17  |110.04
 8  |17  |500.22
 9  |17  |100.99

然后说我可以抓住所有fkID11 个。我希望它排序

 5  |11  |1500
 4  |11  |2000
 6  |11  |10000

或者fkID14 将是

 1  |14  |abc
 3  |14  |def
 2  |14  |ghi

我不知道如何解决这个问题,但尝试使用 Try_Parse 来确定列的值。

如果那行得通,动态sql就可以了。

标签: sqlsql-serversortingdynamic

解决方案


看起来您继承的结构在 sql-server 或任何主要数据库中都没有得到很好的处理(让我想起了过度规范化的 EAV 和 OTLT 模式)。

你可以:

  1. 如果可用,请使用 try_convert 捕获十进制表示。
  2. 使用窗口最大值来识别是否有任何非小数。
  3. 使用使用不同版本的 row_number 的条件语句来获取您的排序。

这是在行动:

declare @fkId int = 11;

select      t.*,
            ord = iif( 
                max(iif(decVal is null, 1, 0)) over() = 1, -- has any non decimals?
                row_number() over(order by myValue), -- string ordering
                row_number() over(order by decVal) -- decimal ordering
            )
from        @myTable t
cross apply (select decVal = try_convert(decimal(10,2), myValue)) ap
where       fkId = @fkId -- replace this with whatever.
order by    ord;

推荐阅读