Trennen Sie Buchstaben von Ziffern in alphanumerischen Zeichenfolgen

9

Ich habe eine alphanumerische Zeichenfolge als Eingabe und möchte zwei Ergebnisse daraus ziehen:

  • Eine Zeichenfolge, in der alle Ziffern entfernt werden

    und

  • Eine Ganzzahl, die die Summe aller Ziffern in der Eingabezeichenfolge ist.

Zum Beispiel für diese Eingabe:

GR35hc7vdH35

Ich möchte die folgende Ausgabe:

| Col1.         |        Col2    |
----------------------------------
| GRhcvdH       |        23      |

Wie kann das gehen?

user93438
quelle

Antworten:

8

SQL Server unterstützt das Ersetzen von Mustern mit mehreren Zeichen nicht. Wenn Sie dies über tun REPLACE, sind möglicherweise 10 Vorgänge erforderlich.

In diesem Sinne wäre eine Möglichkeit ein rekursiver CTE, die Ziffern 0-9 nacheinander zu verarbeiten.

Es ersetzt und überprüft dann die Länge der Vorher- und Nachher-Zeichenfolgen, um festzustellen, wie viele Zeichen dieser Zahl vorhanden waren und was zur Gesamtsumme hinzugefügt werden muss.

DECLARE @Input VARCHAR(8000) = 'GR35hc7vdH35';

WITH R(Level,Input,Accumulator,StringLength)
     AS (SELECT 0,
                Input,
                0,
                DATALENGTH(Input)
         FROM   (SELECT REPLACE(@Input, '0', '')) D(Input)
         UNION ALL
         SELECT NewLevel,
                NewInput,
                Accumulator + NewLevel * ( StringLength - NewStringLength ),
                NewStringLength
         FROM   R
                CROSS APPLY (SELECT Level + 1) C(NewLevel)
                CROSS APPLY (SELECT REPLACE(Input, NewLevel, '')) C2(NewInput)
                CROSS APPLY (SELECT DATALENGTH(NewInput)) C3(NewStringLength)
         WHERE  NewLevel <= 9)
SELECT Input       AS Col1,
       Accumulator AS Col2
FROM   R
WHERE  Level = 9;

Oder Sie können CLR und reguläre Ausdrücke verwenden (SQL Server 2012-kompatible Version).

using System;
using System.Data.SqlTypes;
using System.Collections;
using System.Text.RegularExpressions;

public partial class UserDefinedFunctions
{
    private static readonly Regex digitRegex = new Regex(@"[\d]", RegexOptions.Compiled);

    [Microsoft.SqlServer.Server.SqlFunction(FillRowMethodName = "FillRow",
                                            TableDefinition = @"Stripped NVARCHAR(MAX),
                                                                Total INT")]

    public static IEnumerable ReplaceAndTotalise(SqlString input)
    {
        if (!input.IsNull)
        {
            int total = 0;
            string stripped = digitRegex.Replace((string)input, match =>
            {
                total += int.Parse(match.Value);
                return string.Empty;
            });

            yield return new Tuple<string, int>(stripped, total);
        }
    }

    public static void FillRow(object resultObject, out SqlString stripped, out SqlInt32 total)
    {
        var result = (Tuple<string, int>)resultObject;
        stripped = result.Item1;
        total = result.Item2;

    }
}

Beispiel Verwendung

SELECT Stripped,
       Total
FROM   [dbo].[ReplaceAndTotalise]('GR35hc7vdH35') 
Martin Smith
quelle
5

Versuche Folgendes:

CREATE FUNCTION dbo.AlphaNumericSplitter 
(
    @string varchar(8000)
)
RETURNS TABLE
AS
RETURN  (
    WITH    Alphanumeric (col1)
    AS      (
            -- Put out string into a cte table
            SELECT @string
            ),
            Nmbrs (n)
    AS      (
            -- Numbers so we can split the string
            SELECT  TOP(LEN(@string))
                    ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
            FROM    sys.all_objects AS o1
            CROSS
            JOIN    sys.all_objects AS o2
            ),
            y
    AS      (
            SELECT  N.n
                    a.col1,
                    N.x,
                    -- Get the numbers only
                    Numbers = TRY_CONVERT(int, N.x)
            FROM    Alphanumeric AS a
            CROSS 
            APPLY   (SELECT [x] = SUBSTRING(a.col1, n, 1), Nmbrs.n FROM Nmbrs) AS N
            )
    SELECT  z.Col1,
            Col2 = SUM(y.Numbers)
    FROM    y
    --  Get the letters only
    CROSS
    APPLY   (SELECT (SELECT x + '' FROM y WHERE Numbers IS NULL ORDER BY y.n FOR XML PATH(''))) AS z (Col1)
    GROUP   BY
            z.Col1);
GO

SELECT * FROM AlphaNumericSplitter('GR35hc7vdH35');

Ergebnisse:

Geben Sie hier die Bildbeschreibung ein

Shaneis
quelle
2

So'ne Art

... r.s ...
cross apply (
  select s = sum(cast(substring(mycol,i,1) as int)) 
  from (select top(len(mycol)) i = row_number() over(order by (select null))
    from sys.all_objects,sys.all_objects) tally
  where substring(mycol,i,1) like '[0-9]'
) r
Serg
quelle
0

Verwenden Sie die folgende Funktion, um Alphabete aus Zeichenfolgen zu extrahieren

CREATE FUNCTION dbo.udf_GetAlphabets
(@strAlphaNumeric VARCHAR(256))
RETURNS VARCHAR(256)
AS
BEGIN
DECLARE @intAlpha INT
SET @intAlpha = PATINDEX('%[a-zA-Z]%', @strAlphaNumeric)
BEGIN
WHILE @intAlpha > 0
BEGIN
SET @strAlphaNumeric = STUFF(@strAlphaNumeric, @intAlpha, 1, '' )
SET @intAlpha = PATINDEX('%[a-zA-Z]%', @strAlphaNumeric )
END
END
RETURN ISNULL(@strAlphaNumeric,0)
END
GO

Verwenden Sie die folgende Funktion, um Zahlen aus der Zeichenfolge zu extrahieren

CREATE FUNCTION dbo.udf_GetNumeric
(@strAlphaNumeric VARCHAR(256))
RETURNS VARCHAR(256)
AS
BEGIN
DECLARE @intAlpha INT
SET @intAlpha = PATINDEX('%[^0-9]%', @strAlphaNumeric)
BEGIN
WHILE @intAlpha > 0
BEGIN
SET @strAlphaNumeric = STUFF(@strAlphaNumeric, @intAlpha, 1, '' )
SET @intAlpha = PATINDEX('%[^0-9]%', @strAlphaNumeric )
END
END
RETURN ISNULL(@strAlphaNumeric,0)
END
GO

Verwenden Sie die folgende Abfrage, um beide in einem einzigen Befehl zu extrahieren:

SELECT dbo.udf_GetNumeric(column_name) Number, dbo.udf_GetAlphabets(column_name) Chars
from table_name
Chaos Legion
quelle