Linq to SQL - Wie werden Zahlen als Zeichenfolgen bestellt?

  • Ich habe eine SQL-Varchar-Spalte mit Werten wie 100, 2000 und S5000. Ich möchte, dass sie numerisch und nicht alphabetisch geordnet werden. Wenn es ein Zeichenzeichen gibt, bin ich froh, dass das Zeichen entweder ignoriert wird oder nach den numerischen Werten in der Sortierreihenfolge angezeigt wird.

    In T-SQL könnte ich Folgendes mit

     SELECT * FROM tbl
    ORDER BY
      CASE
        WHEN ISNUMERIC(fld) = 1 THEN CONVERT(INT, fld)
        ELSE 2147483647
        END ASC,
      fld ASC
     

    Ich frage mich, ob es in Linq to SQL eine Möglichkeit gibt, dies zu tun?

    Ansonsten schätze ich meine Alternativen, die Abfrage direkt auszuführen oder eine berechnete Spalte mit Werten wie 00000100, 00002000.000S5000 usw. zu erstellen.

    < strong> Bearbeiten: Ich habe eine Lösung gefunden, obwohl ich nicht sicher bin, wie effizient sie ist.

     from s in q
    orderby (SqlMethods.Like(s.fld, "%[^0-9]%") ? Int32.MaxValue : Convert.ToInt32(s.fld)) ascending, s.fld ascending
    select s;
     
    26 August 2011
    johna
3 answers
  • Ich habe eine Lösung gefunden, obwohl ich nicht sicher bin, wie effizient diese ist.

     from s in q orderby (SqlMethods.Like(s.fld, "%[^0-9]%") ? Int32.MaxValue : Convert.ToInt32(s.fld)) ascending, s.fld ascending select s; 
     
    09 January 2012
    johna
  • Wenn Sie die Ergebnisse bereits aus der Datenbank zurückgegeben haben und Sie die Sortierung im Speicher gerne durchführen, können Sie Folgendes tun:

    Zuerst Definieren Sie eine tryParse -Funktion, die in einer Linq-to-Objects-Abfrage verwendet werden kann:

     Func<string, int> tryParse = s =>
    {
        int i;
        if (!int.TryParse(s, out i))
        {
            i = int.MaxValue;
        }
        return i;
    };
     

    Dann wird die Die eigentliche Abfrage zur Sortierung ist einfach:

     var query =
        from t in tbls.ToArray() // force the linq-to-sql query to execute
        orderby t.fld
        orderby tryParse(t.fld)
        select t;
     

    Einfach, oder?

    25 August 2011
    Enigmativity
  • Ich weiß, die Frage war Linq-to-SQL, aber ich dachte, ich würde Entity Framework 4-Antwort für alle EF-Benutzer geben, die über diese Frage gestolpert sind und nach einem Weg suchen, dies innerhalb dieses Rahmens zu tun. Ich habe keine Erfahrung mit Linq-to-SQL, also würde ich auch wissen, dass dies auch dort funktionieren würde (aber ich bezweifle es).

     Dim results = (From item in ctx.tbl
                   Let sortValue = If(SqlFunctions.IsNumeric(item.fld) = 1, CInt(item.fld), 2147483647)
                   Order By sortValue).ToList()
     

    Dies führt ungefähr zu dieser Store-Abfrage:

     SELECT [Project1].*
    FROM ( SELECT 
        [Extent1].*
        CASE WHEN (1 = (ISNUMERIC([Extent1].[Value]))) THEN  CAST( [Extent1].[Value] AS int) ELSE 99999999 END AS [C2]
        FROM [dbo].[tbl] AS [Extent1]
    )  AS [Project1]
    ORDER BY [Project1].[C2] ASC
     

    Diese Lösung nutzt System.Data.Objects.SqlClient.SqlFunctions , um das SQL ISNUMERIC-Funktion in der Abfrage. Ich möchte darauf hinweisen, dass IsNumeric 1 auch für Dezimalzahlen zurückgibt und ein "dezimaler" Varchar in einen int umgewandelt wird, was zu Problemen führt. Es ist möglicherweise am sichersten, CDbl() anstelle des Wertes CInt() zu verwenden, es sei denn, Sie wissen, dass Ihre Daten niemals etwas anderes als ein "int" -Varchar sind.

    25 August 2011
    ckittel