Custom Sorting Function - of SQL Server

淺唱寂寞╮ 提交于 2019-12-13 07:00:44

问题


I have a column in SQL Server 2005 that stores a version number as a string that i would like to sort by. I have been unable to find out how to sort this column, although i am guessing it would be some kind of custom function or compare algorithm.

Can anyone point me in the right direction of where to start? I may be googling the wrong stuff.

Cheers

Tris


回答1:


I'd use separate int columns (e.g. MajorCol + MinorCol if you are tracking major + minor versions) and run something like

order by MajorCol, MinorCol

in my query.




回答2:


I would look at using a persisted computed column which processes the string into an int or string or something appropriate for sorting in the native SQL Server sort - i.e.

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

So that you can sort by the computed column and get expected results.

Alternatively, you can use such an operation inline, but it might be very slow. In addition scalar UDFs are extremely slow.




回答3:


Creating an SQL CLR function is the way to go. They're extremely fast and powerful. It would be quick and effective as you wouldn't have to change any existing code, and you could specify all the information you need right in your SQL statements.

The SQL CLR function could accept an input string, as well as other parameters specifying which piece of information you'd like to extract from the input string. You could then sort on the return values of the function.

Specifically, I'd create a generic function that accepts three parameters: an input string, a regular expression, and a group name. That function would allow you to pass your database field and a regular expression with named groups right in the SQL statement.

The SQL CLR function would create a Regex, test it against the string, and would ultimately return the matched group's value or null if there was no match or the group was not matched (if the group was optional). Ideally, you'd want to pass the same regular expression to each call (perhaps as a variable like @regex), to take advantage of any CLR caching of the compiled regular expression. The end result would be very flexible and fast.

Regular expression options can be specified inline in the pattern like so: "(?imnsx-imnsx:subexpression)". See: msdn.microsoft.com/en-us/library/yd1hzczs.aspx

The code for such a function would look something like this:

[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         
    }

Your SQL statement could then sort on pieces of your information like so:

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)


来源:https://stackoverflow.com/questions/1322552/custom-sorting-function-of-sql-server

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!