Autor Thema: Gruppensortierung nach alphanumerischem Feld  (Gelesen 143 mal)

alfino

  • Jr. Member
  • **
  • Beiträge: 19
Gruppensortierung nach alphanumerischem Feld
« am: 27. November 2018, 12:23 »
Hallo in die Runde,

ich habe einen Bericht, der die Gruppe nach FASY_Standnummern.STANDNUMMER1. Die Sortierung soll aufsteigend erfolgen.
Leider handelt es sich bei dem Feld um ein varchar, somit wir so sortiert
1
10
110
101
102

Ich muss aber
1
2
3a
4
usw. haben.
Kann ich das über die Funktion 'Formel als Gruppensortierreihenfolge verwenden' lösen? Ich bin in Bericht-Gruppenassistent-Optionen.

Alternativ gibt es ja auch die Option 'Sortierung nach ursprünglicher Reihenfolge', dafür müsste ich die View nach diesem Feld entsprechend sortieren - wie? (SQL select from where... order by [was und wie])

alfino

  • Jr. Member
  • **
  • Beiträge: 19
Re: Gruppensortierung nach alphanumerischem Feld
« Antwort #1 am: 27. November 2018, 17:01 »
Mit dieser function funktioniert die Sortierung:

CREATE FUNCTION [dbo].[fn_CreateAlphanumericSortValue]
(
   @ItemToSort varchar(50)
)
RETURNS varchar(100)
AS
   --==========================================================================================
   -- This function takes an alphanumeric string and encodes it so that it can be properly sorted
   --    against other alphanumeric strings
   -- The encoding will insert a two digit string before each numeric portion of the item to sort
   --    The two digits represent the number of digits in the numeric portion that it will precede (zero-padded)
   -- The encoding will also account for leading zeros in each numeric portion by adding a two digit
   --    string at the end of the item to sort, for each numeric portion.  Those two digits will
   --    represent the number of leading zeros in the numeric portion (zero-padded)
   -- Examples:
   -- ABC1 =     ABC011 00
   -- ABC1ABC1 = ABC011ABC011 00
   -- ABC12    = ABC0212 00
   -- ABC012   = ABC0212 01
   --==========================================================================================
BEGIN
   declare @WorkingItem varchar(50) = @ItemToSort
   declare @DigitCount int = 0
   declare @LeadingZeroCount int = 0
   declare @CurrentNumber varchar(50) = ''
   declare @Leftmost varchar(1) = ''
   declare @LeadingZeroString varchar(50) = ''

   --==========================================================================================
   -- With 50 character input, the worst case output should be 100 characters
   --==========================================================================================
   declare @SortValue varchar(100) = ''   

   --==========================================================================================
   -- We will work thru the input string one character at a time
   --==========================================================================================
   while (len(@WorkingItem) > 0)
   begin
      select @Leftmost = left(@WorkingItem, 1)

      --==========================================================================================
      -- Is the first character a number?
      --==========================================================================================
      if (isnumeric(@Leftmost) = 1)
      begin
         while (isnumeric(@Leftmost) = 1)
         begin
            --==========================================================================================
            -- Parse out all of the consecutive digits to get the current number
            --==========================================================================================
            if (@Leftmost = '0' and @DigitCount = 0)
            begin
               --==========================================================================================
               -- Leading zero -- just count how many we have in this set of digits
               --    We'll add the string for it to the end of our output below
               --==========================================================================================
               select @LeadingZeroCount = @LeadingZeroCount + 1
            end
            else
            begin
               --==========================================================================================
               -- Not a leading zero, so increment the digit count, and remember the current number value
               --==========================================================================================
               select @DigitCount = @DigitCount + 1
               select @CurrentNumber = @CurrentNumber + @Leftmost
            end

            --==========================================================================================
            -- Trim off the character we just checked, get the next character to check and continue the inner loop
            --==========================================================================================
            select @WorkingItem = substring(@WorkingItem, 2, 50)
            select @Leftmost = left(@WorkingItem, 1)
         end -- while (isnumeric(@Leftmost) = 1)

         --==========================================================================================
         -- We now have the current number from our input string
         --    Add the current number's leading zero string to the entire leading zero string
         --==========================================================================================
         if (@LeadingZeroCount < 10)
            select @LeadingZeroString = @LeadingZeroString + '0' + cast(@LeadingZeroCount as varchar)
         else
            select @LeadingZeroString = @LeadingZeroString + cast(@LeadingZeroCount as varchar)

         --==========================================================================================
         -- Add the current number's sort code, along with the current number, to the returned sort value
         --==========================================================================================
         if (@DigitCount < 10)
            select @SortValue = @SortValue + '0' + cast(@DigitCount as varchar) + @CurrentNumber
         else
            select @SortValue = @SortValue + cast(@DigitCount as varchar) + @CurrentNumber

         --==========================================================================================
         -- Reset for the next iteration
         --==========================================================================================
         select @DigitCount = 0
         select @CurrentNumber = ''
         select @LeadingZeroCount = 0
      end -- if (isnumeric(@Leftmost) = 1)

      --==========================================================================================
      -- The character we are currently working with is not a number, just tag it onto our return value
      --    Ignoring whitespace
      --==========================================================================================
      if (@Leftmost != ' ')
         select @SortValue = @SortValue + @Leftmost

      --==========================================================================================
      -- Trim off the character we just checked and continue the main loop
      --==========================================================================================
      select @WorkingItem = substring(@WorkingItem, 2, 50)

   end -- while (len(@WorkingItem) > 0)

   --==========================================================================================
   -- Finally, tag on the leading zero value and return our sort value
   --==========================================================================================
   select @SortValue = @SortValue +  ' ' + @LeadingZeroString

   return @SortValue
END

Allerdings, wenn ich die Sortierung in eine View integriere bekomme ich folgende Meldung, deren Zusammenhang ich nicht verstehe:

Warnung: Die ORDER BY-Klausel wird nur zur Ermittlung der Zeilen verwendet, die von der TOP-Klausel der Sichtdefinition zurückgegeben werden. Die ORDER BY-Klausel gewährleistet bei Abfragen der Sicht keine sortierten Ergebnisse, es sei denn, ORDER BY ist ebenfalls in der Abfrage angegeben.

Ausgegeben wird mir im SQL-Managementstudio die korrekte Sortierung, im Report (Crystal Reports) allerdings nicht.

plinni

  • Experte
  • *****
  • Beiträge: 155
Re: Gruppensortierung nach alphanumerischem Feld
« Antwort #2 am: 28. November 2018, 07:50 »
Ich hätte versucht, die "Zahlen" mittels to_number() umzuwandeln.
Wenn sich sowas wie "3b" findet, dann würde ich nur den numerischen Teil nutzen und in eine Zahl umwandeln (z. B. mit instr() nach Buchstaben suchen und dann splitten; geht aber bestimmt auch über die Unicodewerte).
Is_Numeric () kannst du zunächst als Prüfung nutzen.

hgfa

  • Experte
  • *****
  • Beiträge: 1770
Re: Gruppensortierung nach alphanumerischem Feld
« Antwort #3 am: 30. November 2018, 12:05 »
Hallo,
Mach Dir ein Feld "sort".
//Hilfsvariable zur Sortierung von Feldern, die aus einem Mix aus numerichen/alphanumerichen
//Werten bestehen. Zur Sortierung wird der Feldvariablen ein entsprechender aufsteigender
//Wert vorangestellt
Local NumberVar a := ASC({DeinFeld});
If Val({DeinFeld}) <> 0 Then
// bei Zahl muss auch die "Stringlaenge" beruecksichtigt werden ("354" vor "1234")
   CHR(33 + Len({DeinFeld})) & CStr(Val({DeinFeld}),"#")
 Else
// verhindert dass Kleinbuchstabe vor Grossbuchstabe
   IIf(a > 96, a - 32 + 0.1, a) & {DeinFeld};
Nach diesem Feld kannst Du sortieren.
Gruss Hansgeorg

alfino

  • Jr. Member
  • **
  • Beiträge: 19
Re: Gruppensortierung nach alphanumerischem Feld
« Antwort #4 am: 3. Dezember 2018, 10:56 »
Vielen Dank Hansgeorg, es klappt fast perfekt.

Leider wird mir der Stand 25A am Ende der Liste ausgegeben, d. h. nach der 92 und nicht nach der 25.

Gebe ich mir die Werte der Formel aus, so wird die 25 als #25 ausgegeben, die 25A als $25 und ans Ende gesetzt.

alfino

  • Jr. Member
  • **
  • Beiträge: 19
Re: Gruppensortierung nach alphanumerischem Feld
« Antwort #5 am: 3. Dezember 2018, 13:47 »
Und jetzt weiß ich glaube ich auch, warum die 25A ganz am Schluss ist: Weil sie dreistellig ist, da muss sie natürlich hinter einem 'hunderter' kommen.