Angenommen, Sie wahrscheinlich eine Antwort suchen, der auf N # skaliert werden kann Zeichen in der Schlüssellänge und eine, die den neuen Wert auf die Anzahl der Schlüssel aufteilt, die davon getrennt werden. Ich würde mit einer rekursiven Cte gehen, um es abzuziehen. Fügen Sie mit Ihren Beispieldaten eine weitere Zeile mit 3 Zeichen wie "GHI" hinzu, und führen Sie diesen Code aus, und sehen Sie die Ergebnisskala nach nur 2 Zeichen.
;WITH cteRecursive AS (
SELECT
Id
,AKey
,LEFT(AKey,1) AS NewAKey
,RIGHT(Akey,LEN(AKey) - 1) AS RemainingKey
,AVal
,1 AS [Level]
FROM
@Table
UNION ALL
SELECT
t.Id
,t.AKey
,LEFT(c.RemainingKey,1) AS NewAKey
,RIGHT(RemainingKey,LEN(RemainingKey) - 1) AS RemainingKey
,t.AVal
,c.[Level] + 1 AS [Level]
FROM
@Table t
INNER JOIN cteRecursive c
ON t.Id = c.Id
AND LEN(c.RemainingKey) > 0
)
SELECT
Id
,AKey AS OriginalAKey
,NewAKey
,AVal AS OriginalAVal
,AVal/2.00 AS NewVal
,AVal/CAST(MAX([Level]) OVER (PARTITION BY Id) AS DECIMAL(4,2)) AS NewValAsPortionOfLevel
,AVal/CAST(LEN(AKey) AS DECIMAL(4,2)) AS NewValAsPortionOfKeyLength
FROM
cteRecursive
Hier ist die Tabelle Variable I, wenn Sie es
DECLARE @Table AS TABLE (Id INT IDENTITY(1,1), AKey VARCHAR(100), AVal INT)
INSERT INTO @Table (AKey, AVal)
VALUES ('AB',94),('Q',48),('Z',56),('AB',12),('T',77),('ghi',100)
Wenn nicht den Schlüssel aufteilen wollen Sie mit Hilfe des rekursiven CTE tatsächlich vereinfachen und diesen Weg gehen. Durch die Verwendung von Level < LEN(AKey)
stoppt die Rekursion an der richtigen Stelle und Sie brauchen keine der anderen String-Manipulationen.
;WITH cteRecursive AS (
SELECT
Id
,AKey
,AVal
,1 AS [Level]
FROM
@Table
UNION ALL
SELECT
t.Id
,t.AKey
,t.AVal
,c.[Level] + 1 AS [Level]
FROM
@Table t
INNER JOIN cteRecursive c
ON t.Id = c.Id
AND c.[Level] < LEN(t.Akey)
)
SELECT
Id
,AKey AS OriginalAKey
,AVal AS OriginalAVal
,AVal/2.00 AS NewVal
,AVal/CAST(MAX([Level]) OVER (PARTITION BY Id) AS DECIMAL(4,2)) AS NewValAsPortionOfLevel
,AVal/CAST(LEN(AKey) AS DECIMAL(4,2)) AS NewValAsPortionOfKeyLength
FROM
cteRecursive
Und eine andere Technik, wenn Sie eine sehr große Datenmenge haben und wollen keine Rekursion verwenden, ist, dass Sie eine Tally Tabelle erstellen können, um auf Join. Ich wäre neugierig zu wissen, was besser funktioniert. Ich habe tatsächlich eine permanente Tally-Tabelle zur Verwendung in einigen der Datensatzmanipulation für ETL von Data Warehouse, die ich verwende, aber Sie sollten wahrscheinlich eine temporäre Tabelle anstelle einer Tabellenvariablen auch verwenden. Wie auch immer, hier ist diese Methode.
DECLARE @TallyTable AS TABLE (I INT)
DECLARE @MaxLen INT
SELECT @MaxLen = MAX(LEN(AKey)) FROM @Table
IF (@MaxLen > 0)
BEGIN
WHILE @MaxLen > 0
BEGIN
INSERT INTO @TallyTable (I) VALUES (@MaxLen)
SET @MaxLen -= 1
END
END
SELECT
*
,NewValueApportionedByLengthOfKey = CAST(AVal AS DECIMAL)/ISNULL(NULLIF(LEN(AKey),0),1)
FROM
@Table t
INNER JOIN @TallyTable tt
ON LEN(t.AKey) >= tt.I
Hinweis all diese Methoden übernimmt AKey nie NULL oder 0 Länge sein, aber alle sind leicht zu handhaben, dass angepasst sollte es eine Notwendigkeit sein.
Sind Sie OK, die alle Nicht-AB wird NULL sein? –
Gibt es eine maximale Länge für Akey? – Matt
Alle nonAB - Ich fürchte nein, aber sie können leicht verbunden werden ... Ich schaue auf Ihre Antwort unter. –