Disons que vous êtes probablement une réponse qui peut être mise à l'échelle N Nombre de caractères dans la longueur de la clé et un qui ations la nouvelle valeur au nombre de clés qui en sont séparées. J'irais avec un cte récursif pour le retirer. Avec vos données d'échantillon, ajoutez une autre ligne avec 3 caractères comme 'GHI' et exécutez ce code et voyez l'échelle des résultats au-delà de seulement 2 caractères.
;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
Voici la variable tableau I utilisé si vous le voulez
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)
Si ne pas diviser la clé que vous pouvez réellement simplifier la cte récursive et aller dans cette voie. En utilisant Level < LEN(AKey)
la récursion s'arrêtera au bon endroit et vous n'avez besoin d'aucune des autres manipulations de chaînes.
;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
Et une autre technique si vous avez un ensemble de données très volumineux et ne souhaitez pas utiliser la récursivité, est que vous pouvez construire une table Tally Pour Inscrivez-vous sur. Je serais curieux de savoir qui fonctionne le mieux. J'ai en fait une table de pointage permanente à utiliser dans certaines manipulations d'enregistrements pour l'ETL de l'entrepôt de données que j'utilise, mais vous devriez probablement utiliser une table temporaire plutôt qu'une variable de table. Quoi qu'il en soit, voici cette méthode.
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
Notez toutes ces méthodes supposent AKey ne sera jamais NULL ou 0 longueur, mais tous sont facilement adaptés pour gérer cela devrait-il être nécessaire.
Êtes-vous OK tous les Non-AB seront NULL? –
Y a-t-il une longueur maximale pour Akey? – Matt
Tous nonAB - Je crains que non, mais ils peuvent être facilement rejoints ... Je regarde votre aval. –