Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Remplacement des alphabets par zéro dans une chaîne donnée en SQL

Cela prend un certain nombre de techniques quelque peu avancées combinées pour ce faire. Le premier problème est que vous avez des données délimitées. Cela viole 1NF lorsque vous entasser plusieurs valeurs dans une seule cellule. La deuxième pièce du puzzle est de savoir comment PIVOTER ces données dans un nombre dynamique de colonnes. La plupart des gens autour de SO préfèrent utiliser un PIVOT dynamique. Je préfère utiliser un tableau croisé dynamique à la place. Je trouve la syntaxe moins obtuse et c'est même un peu plus performant qu'un tableau croisé dynamique.

Vous pouvez en savoir plus sur le séparateur que j'utilise généralement ici. http://www.sqlservercentral.com/articles/Tally+Table/72993/ Le principal avantage que ce séparateur offre que la plupart des autres n'offrent pas est qu'il renvoie le numéro de ligne de l'élément dans la liste de valeurs. Ceci est incroyablement utile pour ce type de situation. Si vous voulez vraiment plonger dans le monde des séparateurs, voici plusieurs autres excellentes options. http://sqlperformance.com/2012/07/t-sql -queries/split-strings

Vous pouvez en savoir plus sur les tableaux croisés dynamiques ici. http://www.sqlservercentral.com/articles/Crosstab/65048/

Je ne comprends pas vraiment ce que la table #STATICFILTER a à voir avec cela, donc je l'ai simplement ignoré.

Assurez-vous de comprendre ce code avant de l'implémenter. Les articles référencés détaillent ces techniques.

if OBJECT_ID('tempdb..#MathTemp1') is not null
    drop table #MathTemp1

CREATE TABLE #MathTemp1
(
    IDNUM INTEGER IDENTITY(1,1),
    YEARMONTH VARCHAR(256),
    OutputFormula VARCHAR(256),
    Timedimensiondate Date
)

INSERT INTO #MathTemp1 (YEARMONTH,OUTPUTFORMULA,Timedimensiondate)
VALUES ('CV(N2)  1989: 1','2641.000 + Import - Consumption customs value(1540) + Import - Consumption customs value(1541)','1989-01-01')
,('CV(N2)  1989: 10','54407.000 + Import - Consumption customs value(1540) + 63906.000','1989-10-01')
,('CV(N2)  1990: 11','Import - Consumption customs value(2266) + Import - Consumption customs value(1540) + 53088.000','1990-11-01')
,('CV(N2)  1994: 5','32852.000 + Import - Consumption customs value(1540) + Import - Consumption customs value(1541)','1994-05-01')

declare @StaticPortion nvarchar(2000) = 
    'with OrderedResults as
    (   
        select mt.IDNUM
            , mt.OutputFormula
            , mt.Timedimensiondate
            , mt.YEARMONTH
            , x.ItemNumber
            , LTRIM(RTRIM(x.Item)) as Item
        from #MathTemp1 mt
        cross apply dbo.DelimitedSplit8K(mt.OutputFormula, ''+'') x
    )
    Select IDNUM';

declare @DynamicPortion nvarchar(max) = '';
declare @FinalStaticPortion nvarchar(2000) = ' from OrderedResults Group by IDNUM order by IDNUM';  

with E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS 
(
    SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)

select @DynamicPortion = @DynamicPortion + 
    ', MAX(Case when ItemNumber = ' + CAST(N as varchar(6)) + 'then case when ISNUMERIC(Item) = 1 then convert(numeric(9,3), ltrim(rtrim(Item))) else 0 end end) as Value' + CAST(N as varchar(6)) + CHAR(10)
from cteTally t
where t.N <= 
(
    select MAX(LEN(OutputFormula) - LEN(replace(OutputFormula, '+', ''))) + 1
    from #MathTemp1
)


declare @SqlToExecute nvarchar(max) = @StaticPortion + @DynamicPortion + @FinalStaticPortion;

--select @SqlToExecute
exec sp_executesql @SqlToExecute