Natural (human alpha-numeric) sort in Microsoft SQL 2005

Mamy dużą bazę danych, na której mamy paginację po stronie DB. Jest to szybkie, zwracanie strony 50 wierszy z milionów rekordów w niewielkim ułamku sekundy.

Użytkownicy mogą definiować własne sortowanie, zasadniczo wybierając kolumnę do sortowania według. Kolumny są dynamiczne-niektóre mają wartości liczbowe, niektóre daty i niektóre teksty.

Podczas gdy większość sortuje zgodnie z oczekiwaniami tekst sortuje w głupi sposób. Cóż, mówię głupi, to ma sens dla komputerów, ale frustruje użytkowników.

Dla przykład, sortowanie według ID rekordu łańcuchowego daje coś w stylu:

rec1
rec10
rec14
rec2
rec20
rec3
rec4

...i tak dalej.

Chcę, aby to uwzględniało liczbę, więc:

rec1
rec2
rec3
rec4
rec10
rec14
rec20

Nie mogę kontrolować wejścia (w przeciwnym razie formatowałbym tylko wiodące 000s) i nie mogę polegać na jednym formacie - niektóre są takie rzeczy jak " {alpha code}-{dept code} - {rec id}".

Znam kilka sposobów, aby to zrobić w C#, ale nie mogę ściągnąć wszystkich rekordów, aby je posortować, ponieważ byłoby to powolne.

Czy ktoś zna sposób na szybko zastosować sortowanie naturalne w Sql server?

Używamy:

ROW_NUMBER() over (order by {field name} asc)
/ Align = "left" /

Możemy dodać wyzwalacze, chociaż nie chcemy. wszystkie ich wejścia są parametryzowane i tym podobne, ale nie mogę zmienić formatu - jeśli dodają "rec2" i "rec10" oczekują, że zostaną zwrócone w taki sam sposób, w naturalnej kolejności.


Mamy poprawne dane wejściowe użytkownika, które śledzą różne formaty dla różnych klientów.

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

Podczas gdy inny może pójść: grp1rec1, grp1rec2,... grp20rec300, grp20rec301

Kiedy mówię, że nie możemy kontrolować wejścia, mam na myśli to, że nie możemy zmusić użytkowników do zmiany tych standardów - mają one wartość taką jak grp1rec1 i nie mogę sformatować jej jako grp01rec001, ponieważ byłoby to zmianą czegoś używanego do wyszukiwania i linkowania do zewnętrznych systemów.

Te formaty bardzo się różnią, ale często są mieszaniną liter i cyfr.

Sortowanie ich w C# jest łatwe - po prostu podziel je na { "grp", 20, "rec", 301 }, a następnie po kolei porównaj wartości sekwencji.

Jakkolwiek mogą być miliony rekordów i dane są paged, potrzebuję sortowania na serwerze SQL.

SQL server sortuje według wartości, a nie porównania - w C# mogę podzielić wartości do porównania, ale w SQL potrzebuję logiki, która (bardzo szybko) otrzymuje pojedynczą wartość, która konsekwentnie sortuje.

@moebius - Twoja odpowiedź może się udać, ale wydaje mi się, że brzydki kompromis jest dodanie klucza sortowania dla wszystkich te wartości tekstowe.

Author: ChrisF, 2008-08-29

13 answers

Większość rozwiązań opartych na SQL widziałem przerwy, gdy dane stają się wystarczająco skomplikowane (np. więcej niż jeden lub dwa numery w nim). Początkowo próbowałem zaimplementować funkcję NaturalSort w T-SQL, która spełniała moje wymagania( między innymi obsługiwała dowolną liczbę liczb w ciągu znaków), ale wydajność była sposób zbyt wolna.

Ostatecznie napisałem skalarną funkcję CLR w C#, aby pozwolić na naturalny sort, a nawet z nieoptymalizowanym kodem wydajność wywołująca ją z SQL Server jest ślepo szybki. Posiada następujące cechy:

    Pierwsze 1000 znaków będzie sortowane poprawnie (łatwo zmodyfikowane w kodzie lub wykonane w parametrze)
  • odpowiednio sortuje dziesiętne, więc 123.333 jest przed 123.45
  • z powodu powyższego, prawdopodobnie nie sortuje rzeczy takich jak adresy IP poprawnie; jeśli chcesz innego zachowania, zmodyfikuj kod
  • obsługuje sortowanie łańcucha o dowolnej liczbie liczb w it
  • poprawnie sortuje liczby o długości do 25 cyfr (łatwo modyfikować w kodzie lub przekształcić w parametr)

Kod jest tutaj:

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');
    }
}

Aby to zarejestrować i wywołać z SQL Server, uruchom następujące polecenia w analizatorze zapytań:

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

Wtedy możesz go używać tak:

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

Uwaga: Jeśli pojawi się błąd w SQL Server wzdłuż linii wykonywanie kodu użytkownika w. NET Framework jest wyłączone. Enable " CLR enabled" Opcja konfiguracji., postępuj zgodnie z instrukcjami tutaj {[33] } aby go włączyć. Zanim to zrobisz, upewnij się, że bierzesz pod uwagę konsekwencje związane z bezpieczeństwem. Jeśli nie jesteś administratorem db, przed dokonaniem jakichkolwiek zmian w konfiguracji serwera koniecznie porozmawiaj o tym z administratorem.

Note2 : ten kod nie obsługuje poprawnie internacjonalizacji(np. zakłada, że znacznikiem dziesiętnym jest".", nie jest zoptymalizowany pod kątem prędkości itp. Sugestie dotyczące poprawy to Witamy!

Edit: zmienił nazwę funkcji na Naturalize zamiast NaturalSort, ponieważ nie wykonuje ona żadnego rzeczywistego sortowania.

 29
Author: D'Arcy Rittich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-28 16:00:49
order by LEN(value), value
Nie jest idealny, ale działa dobrze w wielu przypadkach.
 43
Author: Jeff Atwood,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-06 06:16:00

Wiem, że to stare pytanie, ale właśnie na nie trafiłem, ponieważ nie ma na nie zaakceptowanej odpowiedzi.

Zawsze używałem sposobów podobnych do tego:

SELECT [Column] FROM [Table]
ORDER BY RIGHT(REPLICATE('0', 1000) + LTRIM(RTRIM(CAST([Column] AS VARCHAR(MAX)))), 1000)

Jedynymi częstymi czasami, kiedy to ma problemy, jest to, czy Twoja kolumna nie zostanie rzucona na VARCHAR (MAX), lub jeśli LEN ([Column]) > 1000 (ale możesz zmienić to 1000 na coś innego, jeśli chcesz), ale możesz użyć tego przybliżonego pomysłu do tego, czego potrzebujesz.

Również jest to znacznie gorsza wydajność niż normalne zamówienie przez [kolumnę], ale robi podaj wynik żądany w OP.

Edit: aby jeszcze bardziej wyjaśnić, powyższe nie zadziała, jeśli masz wartości dziesiętne, takie jak posiadanie 1, 1.15 i 1.5, (będą sortować jako {1, 1.5, 1.15}), ponieważ nie jest to to, o co prosi się w OP, ale można to łatwo zrobić przez:

SELECT [Column] FROM [Table]
ORDER BY REPLACE(RIGHT(REPLICATE('0', 1000) + LTRIM(RTRIM(CAST([Column] AS VARCHAR(MAX)))) + REPLICATE('0', 100 - CHARINDEX('.', REVERSE(LTRIM(RTRIM(CAST([Column] AS VARCHAR(MAX))))), 1)), 1000), '.', '0')

Wynik: {1, 1.15, 1.5}

I nadal wszystko całkowicie w SQL. To nie posortuje adresów IP, ponieważ teraz dostajesz bardzo konkretne kombinacje liczb w przeciwieństwie do zwykłego tekstu + liczba.

 14
Author: Seph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-29 12:50:32

Oto rozwiązanie napisane dla SQL 2000. Prawdopodobnie można go ulepszyć dla nowszych wersji SQL.

/**
 * Returns a string formatted for natural sorting. This function is very useful when having to sort alpha-numeric strings.
 *
 * @author Alexandre Potvin Latreille (plalx)
 * @param {nvarchar(4000)} string The formatted string.
 * @param {int} numberLength The length each number should have (including padding). This should be the length of the longest number. Defaults to 10.
 * @param {char(50)} sameOrderChars A list of characters that should have the same order. Ex: '.-/'. Defaults to empty string.
 *
 * @return {nvarchar(4000)} A string for natural sorting.
 * Example of use: 
 * 
 *      SELECT Name FROM TableA ORDER BY Name
 *  TableA (unordered)              TableA (ordered)
 *  ------------                    ------------
 *  ID  Name                        ID  Name
 *  1.  A1.                         1.  A1-1.       
 *  2.  A1-1.                       2.  A1.
 *  3.  R1             -->          3.  R1
 *  4.  R11                         4.  R11
 *  5.  R2                          5.  R2
 *
 *  
 *  As we can see, humans would expect A1., A1-1., R1, R2, R11 but that's not how SQL is sorting it.
 *  We can use this function to fix this.
 *
 *      SELECT Name FROM TableA ORDER BY dbo.udf_NaturalSortFormat(Name, default, '.-')
 *  TableA (unordered)              TableA (ordered)
 *  ------------                    ------------
 *  ID  Name                        ID  Name
 *  1.  A1.                         1.  A1.     
 *  2.  A1-1.                       2.  A1-1.
 *  3.  R1              -->         3.  R1
 *  4.  R11                         4.  R2
 *  5.  R2                          5.  R11
 */
ALTER FUNCTION [dbo].[udf_NaturalSortFormat](
    @string nvarchar(4000),
    @numberLength int = 10,
    @sameOrderChars char(50) = ''
)
RETURNS varchar(4000)
AS
BEGIN
    DECLARE @sortString varchar(4000),
        @numStartIndex int,
        @numEndIndex int,
        @padLength int,
        @totalPadLength int,
        @i int,
        @sameOrderCharsLen int;

    SELECT 
        @totalPadLength = 0,
        @string = RTRIM(LTRIM(@string)),
        @sortString = @string,
        @numStartIndex = PATINDEX('%[0-9]%', @string),
        @numEndIndex = 0,
        @i = 1,
        @sameOrderCharsLen = LEN(@sameOrderChars);

    -- Replace all char that have the same order by a space.
    WHILE (@i <= @sameOrderCharsLen)
    BEGIN
        SET @sortString = REPLACE(@sortString, SUBSTRING(@sameOrderChars, @i, 1), ' ');
        SET @i = @i + 1;
    END

    -- Pad numbers with zeros.
    WHILE (@numStartIndex <> 0)
    BEGIN
        SET @numStartIndex = @numStartIndex + @numEndIndex;
        SET @numEndIndex = @numStartIndex;

        WHILE(PATINDEX('[0-9]', SUBSTRING(@string, @numEndIndex, 1)) = 1)
        BEGIN
            SET @numEndIndex = @numEndIndex + 1;
        END

        SET @numEndIndex = @numEndIndex - 1;

        SET @padLength = @numberLength - (@numEndIndex + 1 - @numStartIndex);

        IF @padLength < 0
        BEGIN
            SET @padLength = 0;
        END

        SET @sortString = STUFF(
            @sortString,
            @numStartIndex + @totalPadLength,
            0,
            REPLICATE('0', @padLength)
        );

        SET @totalPadLength = @totalPadLength + @padLength;
        SET @numStartIndex = PATINDEX('%[0-9]%', RIGHT(@string, LEN(@string) - @numEndIndex));
    END

    RETURN @sortString;
END
 7
Author: plalx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-31 18:18:02

Wiem, że w tym momencie jest to trochę stare, ale w poszukiwaniu lepszego rozwiązania natknąłem się na to pytanie. Obecnie używam funkcji, aby zamówić przez. Działa dobrze w moim celu sortowania rekordów, które są nazwane mieszanymi liczbami alfanumerycznymi ('pozycja 1',' Pozycja 10',' Pozycja 2', itp.)

CREATE FUNCTION [dbo].[fnMixSort]
(
    @ColValue NVARCHAR(255)
)
RETURNS NVARCHAR(1000)
AS

BEGIN
    DECLARE @p1 NVARCHAR(255),
        @p2 NVARCHAR(255),
        @p3 NVARCHAR(255),
        @p4 NVARCHAR(255),
        @Index TINYINT

    IF @ColValue LIKE '[a-z]%'
        SELECT  @Index = PATINDEX('%[0-9]%', @ColValue),
            @p1 = LEFT(CASE WHEN @Index = 0 THEN @ColValue ELSE LEFT(@ColValue, @Index - 1) END + REPLICATE(' ', 255), 255),
            @ColValue = CASE WHEN @Index = 0 THEN '' ELSE SUBSTRING(@ColValue, @Index, 255) END
    ELSE
        SELECT  @p1 = REPLICATE(' ', 255)

    SELECT  @Index = PATINDEX('%[^0-9]%', @ColValue)

    IF @Index = 0
        SELECT  @p2 = RIGHT(REPLICATE(' ', 255) + @ColValue, 255),
            @ColValue = ''
    ELSE
        SELECT  @p2 = RIGHT(REPLICATE(' ', 255) + LEFT(@ColValue, @Index - 1), 255),
            @ColValue = SUBSTRING(@ColValue, @Index, 255)

    SELECT  @Index = PATINDEX('%[0-9,a-z]%', @ColValue)

    IF @Index = 0
        SELECT  @p3 = REPLICATE(' ', 255)
    ELSE
        SELECT  @p3 = LEFT(REPLICATE(' ', 255) + LEFT(@ColValue, @Index - 1), 255),
            @ColValue = SUBSTRING(@ColValue, @Index, 255)

    IF PATINDEX('%[^0-9]%', @ColValue) = 0
        SELECT  @p4 = RIGHT(REPLICATE(' ', 255) + @ColValue, 255)
    ELSE
        SELECT  @p4 = LEFT(@ColValue + REPLICATE(' ', 255), 255)

    RETURN  @p1 + @p2 + @p3 + @p4

END

Następnie wywołaj

select item_name from my_table order by fnMixSort(item_name)

Łatwo potraja czas przetwarzania dla prostego odczytu danych, więc może nie być idealnym rozwiązaniem.

 6
Author: JazzHands,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-07 02:45:32

Odpowiedź RedFilter jest świetna dla zbiorów danych o rozsądnych rozmiarach, gdzie indeksowanie nie jest krytyczne, jednak jeśli chcesz mieć indeks, wymagane jest kilka poprawek.

Po pierwsze, zaznacz funkcję jako nie wykonującą dostępu do danych i będącą deterministyczną i precyzyjną:

[SqlFunction(DataAccess = DataAccessKind.None,
                          SystemDataAccess = SystemDataAccessKind.None,
                          IsDeterministic = true, IsPrecise = true)]

Następnie MSSQL ma limit 900 bajtów na rozmiarze klucza indeksu, więc jeśli naturalizowana wartość jest jedyną wartością w indeksie, musi mieć maksymalnie 450 znaków. Jeśli indeks zawiera wiele kolumn, zwraca wartość musi być jeszcze mniejsza. Dwie zmiany:

CREATE FUNCTION Naturalize(@str AS nvarchar(max)) RETURNS nvarchar(450)
    EXTERNAL NAME ClrExtensions.Util.Naturalize

Oraz w kodzie C#:

const int maxLength = 450;

Na koniec musisz dodać kolumnę obliczeniową do tabeli i musi ona zostać utrzymana (ponieważ MSSQL nie może udowodnić, że Naturalize jest deterministyczna i precyzyjna), co oznacza, że naturalizowana wartość jest faktycznie przechowywana w tabeli, ale nadal jest utrzymywana automatycznie:

ALTER TABLE YourTable ADD nameNaturalized AS dbo.Naturalize(name) PERSISTED

Możesz teraz utworzyć indeks!

CREATE INDEX idx_YourTable_n ON YourTable (nameNaturalized)

Wprowadziłem też kilka zmian w kodzie Redfiltera: używając znaków dla jasności, włączenie usuwania duplikatów w pętli głównej, wyjście, gdy wynik jest dłuższy niż limit, ustawienie maksymalnej długości Bez podłańcucha itp. Oto wynik:

using System.Data.SqlTypes;
using System.Text;
using Microsoft.SqlServer.Server;

public static class Util
{
    [SqlFunction(DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None, IsDeterministic = true, IsPrecise = true)]
    public static SqlString Naturalize(string str)
    {
        if (string.IsNullOrEmpty(str))
            return str;

        const int maxLength = 450;
        const int padLength = 15;

        bool isDecimal = false;
        bool wasSpace = false;
        int numStart = 0;
        int numLength = 0;

        var sb = new StringBuilder();
        for (var i = 0; i < str.Length; i++)
        {
            char c = str[i];
            if (c >= '0' && c <= '9')
            {
                if (numLength == 0)
                    numStart = i;
                numLength++;
            }
            else
            {
                if (numLength > 0)
                {
                    sb.Append(pad(str.Substring(numStart, numLength), isDecimal, padLength));
                    numLength = 0;
                }
                if (c != ' ' || !wasSpace)
                    sb.Append(c);
                isDecimal = c == '.';
                if (sb.Length > maxLength)
                    break;
            }
            wasSpace = c == ' ';
        }
        if (numLength > 0)
            sb.Append(pad(str.Substring(numStart, numLength), isDecimal, padLength));

        if (sb.Length > maxLength)
            sb.Length = maxLength;
        return sb.ToString();
    }

    private static string pad(string num, bool isDecimal, int padLength)
    {
        return isDecimal ? num.PadRight(padLength, '0') : num.PadLeft(padLength, '0');
    }
}
 6
Author: Roman Starkov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:17:53

Oto inne rozwiązanie, które lubię: http://www.dreamchain.com/sql-and-alpha-numeric-sort-order/

To nie jest Microsoft SQL, ale ponieważ znalazłem się tutaj, gdy szukałem rozwiązania dla Postgres, pomyślałem, że dodanie tego tutaj pomoże innym.

 3
Author: Simon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-14 09:05:31

Dla następujących danych varchar:

BR1
BR2
External Location
IR1
IR2
IR3
IR4
IR5
IR6
IR7
IR8
IR9
IR10
IR11
IR12
IR13
IR14
IR16
IR17
IR15
VCR

To działało najlepiej dla mnie:

ORDER BY substring(fieldName, 1, 1), LEN(fieldName)
 3
Author: Gut Feeling,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-07 23:33:42

Jeśli masz problem z załadowaniem danych z DB do sortowania w C#, to jestem pewien, że będziesz rozczarowany jakimkolwiek podejściem do robienia tego programowo w DB. Kiedy serwer ma sortować, musi obliczyć" postrzeganą " kolejność tak , jak ty byś to zrobił-za każdym razem.

Sugerowałbym dodanie dodatkowej kolumny do przechowywania wstępnie przetworzonego sortowalnego łańcucha, używając jakiejś metody C#, gdy dane są po raz pierwszy wstawiane. Możesz spróbować przekonwertować liczby na stałą szerokość zakresy, na przykład, więc "xyz1" zamieni się w "xyz00000001". Następnie możesz użyć normalnego sortowania SQL Server.

Z narażeniem własnego klaksonu, napisałem artykuł CodeProject implementujący problem przedstawiony w artykule CodingHorror. Zapraszam do wykraść z mojego kodu .

 1
Author: Chris Wuestefeld,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 21:34:51

Właśnie czytałem gdzieś artykuł o takim temacie. Najważniejsze jest to, że do sortowania danych potrzebna jest tylko liczba całkowita, podczas gdy łańcuch 'rec' należy do interfejsu użytkownika. Można podzielić informacje na dwa pola, powiedzmy alpha i num, Sortuj według alpha i num (osobno), a następnie wyświetlając ciąg złożony przez alpha + num. Możesz użyć obliczonej kolumny do skomponowania ciągu znaków lub widoku. Hope it helps

 0
Author: M.Turrini,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-15 10:14:50

Możesz użyć następującego kodu, aby rozwiązać problem:

Select *, 
    substring(Cote,1,len(Cote) - Len(RIGHT(Cote, LEN(Cote) - PATINDEX('%[0-9]%', Cote)+1)))alpha,
    CAST(RIGHT(Cote, LEN(Cote) - PATINDEX('%[0-9]%', Cote)+1) AS INT)intv 
FROM Documents 
   left outer join Sites ON Sites.IDSite = Documents.IDSite 
Order BY alpha, intv

Pozdrawiam, [email protected]

 0
Author: Ian Boyd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-15 15:25:12

Po prostu Sortuj według

ORDER BY 
cast (substring(name,(PATINDEX('%[0-9]%',name)),len(name))as int)

 ##
 0
Author: jack.mike.info,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-16 05:35:37

Nadal nie rozumiem (prawdopodobnie z powodu mojego kiepskiego angielskiego).

Możesz spróbować:
ROW_NUMBER() OVER (ORDER BY dbo.human_sort(field_name) ASC)
Ale to nie zadziała dla milionów płyt.

Dlatego zasugerowałem użycie triggera, który wypełnia oddzielna kolumna z wartością ludzką .

Ponadto:

  • wbudowane funkcje T-SQL są naprawdę slow i Microsoft sugerują użycie Zamiast tego działa. NET.
  • wartość ludzka jest stała, więc nie ma sensu jej obliczać za każdym razem gdy zapytanie działa.
 -1
Author: Grzegorz Gierlik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-29 21:54:43