sql >> Base de Datos >  >> RDS >> Sqlserver

Reemplazar alfabetos a cero en cualquier cadena dada en SQL

Esto requiere una serie de técnicas algo avanzadas combinadas para hacer esto. El primer problema es que tienes datos delimitados. Esto viola 1NF cuando metes múltiples valores en una sola celda. La segunda pieza del rompecabezas es cómo PIVOTAR estos datos en un número dinámico de columnas. La mayoría de las personas en SO prefieren usar un PIVOT dinámico. Prefiero usar una tabulación cruzada dinámica en su lugar. La sintaxis me parece menos obtusa e incluso tiene un poco más de rendimiento que una tabulación cruzada dinámica.

Puede leer sobre el divisor que normalmente uso aquí. http://www.sqlservercentral.com/articles/Tally+Table/72993/ La principal ventaja que ofrece este divisor que la mayoría de los demás no ofrece es que devuelve el número de fila del elemento dentro de la lista de valores. Esto es increíblemente útil para este tipo de situación. Si realmente quieres sumergirte en el mundo de los divisores, aquí tienes otras opciones excelentes. http://sqlperformance.com/2012/07/t-sql -consultas/cadenas divididas

Puede leer más sobre las tabulaciones cruzadas dinámicas aquí. http://www.sqlservercentral.com/articles/Crosstab/65048/

Realmente no entiendo qué tiene que ver la tabla #STATICFILTER con esto, así que simplemente la ignoré.

Asegúrese de comprender este código antes de implementarlo. Los artículos a los que se hace referencia entran en gran detalle sobre estas técnicas.

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