【问题标题】:Custom Sorting Function - of SQL ServerSQL Server的自定义排序功能
【发布时间】:2009-08-24 13:48:31
【问题描述】:

我在 SQL Server 2005 中有一个列,它将版本号存储为我想要排序的字符串。我一直无法找出如何对这一列进行排序,尽管我猜这将是某种自定义函数或比较算法。

谁能指出我从哪里开始的正确方向?我可能在谷歌上搜索错误的东西。

干杯

三分

【问题讨论】:

  • 它究竟以什么格式存储?

标签: sql-server sorting user-defined-functions


【解决方案1】:

我会使用单独的 int 列(例如,如果您正在跟踪主要 + 次要版本,则使用 MajorCol + MinorCol)并运行类似

order by MajorCol, MinorCol

在我的查询中。

【讨论】:

    【解决方案2】:

    我会考虑使用持久化计算列,它将字符串处理为 int 或字符串或适合在本机 SQL Server 排序中排序的东西 - 即

    '1.1.1.1' -> '001.001.001.001'
    '10.10.10.10' -> '010.010.010.010'
    '1.10.1.10' -> '001.010.001.010'
    

    这样您就可以按计算列进行排序并获得预期的结果。

    或者,您可以内联使用这样的操作,但它可能会很慢。此外,标量 UDF 非常慢。

    【讨论】:

    • 我开始怀疑是否可以将版本信息存储在单独的 int 列中。
    【解决方案3】:

    创建一个 SQL CLR 函数是可行的方法。它们非常快速和强大。这将是快速有效的,因为您不必更改任何现有代码,并且您可以在 SQL 语句中指定您需要的所有信息。

    SQL CLR 函数可以接受输入字符串,以及其他指定您想从输入字符串中提取哪条信息的参数。然后,您可以对函数的返回值进行排序。

    具体来说,我将创建一个接受三个参数的通用函数:输入字符串、正则表达式和组名。该函数将允许您在 SQL 语句中传递您的数据库字段和带有命名组的正则表达式。

    SQL CLR 函数将创建一个正则表达式,根据字符串对其进行测试,并最终返回匹配组的值,如果不匹配或组不匹配(如果组是可选的),则返回 null。理想情况下,您希望将相同的正则表达式传递给每个调用(可能作为@regex 之类的变量),以利用已编译正则表达式的任何 CLR 缓存。最终结果将非常灵活和快速。

    可以像这样在模式中内联指定正则表达式选项:“(?imnsx-imnsx:subexpression)”。见:msdn.microsoft.com/en-us/library/yd1hzczs.aspx

    此类函数的代码如下所示:

    [SqlFunction(IsDeterministic=true,IsPrecise=true,DataAccess=DataAccessKind.None,SystemDataAccess=SystemDataAccessKind.None)]
    public static SqlString RegexMatchNamedGroup( SqlChars input, SqlString pattern, SqlString group_name )
        {
            Regex regex = new Regex( pattern.Value );
            Match match = regex.Match( new string( input.Value ) );
            if (!match.Success) //return null if match failed
                return SqlString.Null;
            if (group_name.IsNull) //return entire string if matched when no group name is specified
                return match.Value;
            Group group = match.Groups[group_name.Value];
            if (group.Success)
                return group.Value; //return matched group value
            else
                return SqlString.Null; //return null if named group was not matched         
        }
    

    然后,您的 SQL 语句可以对您的信息片段进行排序,如下所示:

    declare @regex nvarchar(2000) = '^(?<Major>\d{1,3})\.(?<Minor>\d{1,3})';
    
    select VersionNumber
    from YourTable
    order by
    Cast(RegexMatchNamedGroup( VersionNumber, @regex, 'Major') as int),
    Cast(RegexMatchNamedGroup( VersionNumber, @regex, 'Minor') as int)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-15
      • 1970-01-01
      相关资源
      最近更新 更多