Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 573027
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 13, 20262026-05-13T13:40:51+00:00 2026-05-13T13:40:51+00:00

We have a large database on which we have DB side pagination. This is

  • 0

We have a large database on which we have DB side pagination. This is quick, returning a page of 50 rows from millions of records in a small fraction of a second.

Users can define their own sort, basically choosing what column to sort by. Columns are dynamic – some have numeric values, some dates and some text.

While most sort as expected text sorts in a dumb way. Well, I say dumb, it makes sense to computers, but frustrates users.

For instance, sorting by a string record id gives something like:

rec1
rec10
rec14
rec2
rec20
rec3
rec4

…and so on.

I want this to take account of the number, so:

rec1
rec2
rec3
rec4
rec10
rec14
rec20

I can’t control the input (otherwise I’d just format in leading 000s) and I can’t rely on a single format – some are things like “{alpha code}-{dept code}-{rec id}”.

I know a few ways to do this in C#, but can’t pull down all the records to sort them, as that would be to slow.

Does anyone know a way to quickly apply a natural sort in Sql server?


We’re using:

ROW_NUMBER() over (order by {field name} asc)

And then we’re paging by that.

We can add triggers, although we wouldn’t. All their input is parametrised and the like, but I can’t change the format – if they put in “rec2” and “rec10” they expect them to be returned just like that, and in natural order.


We have valid user input that follows different formats for different clients.

One might go rec1, rec2, rec3, … rec100, rec101

While another might go: grp1rec1, grp1rec2, … grp20rec300, grp20rec301

When I say we can’t control the input I mean that we can’t force users to change these standards – they have a value like grp1rec1 and I can’t reformat it as grp01rec001, as that would be changing something used for lookups and linking to external systems.

These formats vary a lot, but are often mixtures of letters and numbers.

Sorting these in C# is easy – just break it up into { "grp", 20, "rec", 301 } and then compare sequence values in turn.

However there may be millions of records and the data is paged, I need the sort to be done on the SQL server.

SQL server sorts by value, not comparison – in C# I can split the values out to compare, but in SQL I need some logic that (very quickly) gets a single value that consistently sorts.

@moebius – your answer might work, but it does feel like an ugly compromise to add a sort-key for all these text values.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-13T13:40:52+00:00Added an answer on May 13, 2026 at 1:40 pm

    Most of the SQL-based solutions I have seen break when the data gets complex enough (e.g. more than one or two numbers in it). Initially I tried implementing a NaturalSort function in T-SQL that met my requirements (among other things, handles an arbitrary number of numbers within the string), but the performance was way too slow.

    Ultimately, I wrote a scalar CLR function in C# to allow for a natural sort, and even with unoptimized code the performance calling it from SQL Server is blindingly fast. It has the following characteristics:

    • will sort the first 1,000 characters or so correctly (easily modified in code or made into a parameter)
    • properly sorts decimals, so 123.333 comes before 123.45
    • because of above, will likely NOT sort things like IP addresses correctly; if you wish different behaviour, modify the code
    • supports sorting a string with an arbitrary number of numbers within it
    • will correctly sort numbers up to 25 digits long (easily modified in code or made into a parameter)

    The code is here:

    using System;
    using System.Data.SqlTypes;
    using System.Text;
    using Microsoft.SqlServer.Server;
    
    public class UDF
    {
        [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic=true)]
        public static SqlString Naturalize(string val)
        {
            if (String.IsNullOrEmpty(val))
                return val;
    
            while(val.Contains("  "))
                val = val.Replace("  ", " ");
    
            const int maxLength = 1000;
            const int padLength = 25;
    
            bool inNumber = false;
            bool isDecimal = false;
            int numStart = 0;
            int numLength = 0;
            int length = val.Length < maxLength ? val.Length : maxLength;
    
            //TODO: optimize this so that we exit for loop once sb.ToString() >= maxLength
            var sb = new StringBuilder();
            for (var i = 0; i < length; i++)
            {
                int charCode = (int)val[i];
                if (charCode >= 48 && charCode <= 57)
                {
                    if (!inNumber)
                    {
                        numStart = i;
                        numLength = 1;
                        inNumber = true;
                        continue;
                    }
                    numLength++;
                    continue;
                }
                if (inNumber)
                {
                    sb.Append(PadNumber(val.Substring(numStart, numLength), isDecimal, padLength));
                    inNumber = false;
                }
                isDecimal = (charCode == 46);
                sb.Append(val[i]);
            }
            if (inNumber)
                sb.Append(PadNumber(val.Substring(numStart, numLength), isDecimal, padLength));
    
            var ret = sb.ToString();
            if (ret.Length > maxLength)
                return ret.Substring(0, maxLength);
    
            return ret;
        }
    
        static string PadNumber(string num, bool isDecimal, int padLength)
        {
            return isDecimal ? num.PadRight(padLength, '0') : num.PadLeft(padLength, '0');
        }
    }
    

    To register this so that you can call it from SQL Server, run the following commands in Query Analyzer:

    CREATE ASSEMBLY SqlServerClr FROM 'SqlServerClr.dll' --put the full path to DLL here
    go
    CREATE FUNCTION Naturalize(@val as nvarchar(max)) RETURNS nvarchar(1000) 
    EXTERNAL NAME SqlServerClr.UDF.Naturalize
    go
    

    Then, you can use it like so:

    select *
    from MyTable
    order by dbo.Naturalize(MyTextField)
    

    Note: If you get an error in SQL Server along the lines of Execution of user code in the .NET Framework is disabled. Enable “clr enabled” configuration option., follow the instructions here to enable it. Make sure you consider the security implications before doing so. If you are not the db admin, make sure you discuss this with your admin before making any changes to the server configuration.

    Note2: This code does not properly support internationalization (e.g., assumes the decimal marker is “.”, is not optimized for speed, etc. Suggestions on improving it are welcome!

    Edit: Renamed the function to Naturalize instead of NaturalSort, since it does not do any actual sorting.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Ask A Question

Stats

  • Questions 357k
  • Answers 357k
  • Best Answers 0
  • User 1
  • Popular
  • Answers
  • Editorial Team

    How to approach applying for a job at a company ...

    • 7 Answers
  • Editorial Team

    What is a programmer’s life like?

    • 5 Answers
  • Editorial Team

    How to handle personal stress caused by utterly incompetent and ...

    • 5 Answers
  • Editorial Team
    Editorial Team added an answer The other answers are correct. Here is some code you… May 14, 2026 at 9:40 am
  • Editorial Team
    Editorial Team added an answer you ruin the noConflict concept by reassigning the jquery to… May 14, 2026 at 9:40 am
  • Editorial Team
    Editorial Team added an answer If you get that particular error, you don't actually have… May 14, 2026 at 9:40 am

Related Questions

No related questions found

Trending Tags

analytics british company computer developers django employee employer english facebook french google interview javascript language life php programmer programs salary

Top Members

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.