Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Sostituzione degli alfabeti a zero in una determinata stringa in SQL

Ciò richiede una serie di tecniche alquanto avanzate combinate per farlo. Il primo problema è che hai dei dati delimitati. Ciò viola 1NF quando si stipano più valori in una singola cella. Il secondo pezzo del puzzle è come PIVOT questi dati in un numero dinamico di colonne. La maggior parte delle persone intorno a SO preferisce utilizzare un PIVOT dinamico. Preferisco invece utilizzare una scheda incrociata dinamica. Trovo la sintassi meno ottusa ed è anche un po' più performante di una tabella incrociata dinamica.

Puoi leggere lo splitter che di solito uso qui. http://www.sqlservercentral.com/articles/Tally+Table/72993/ Il vantaggio principale che offre questo splitter rispetto alla maggior parte degli altri è che restituisce il numero di riga dell'elemento all'interno dell'elenco di valori. Questo è incredibilmente utile per questo tipo di situazione. Se vuoi davvero tuffarti nel mondo degli splitter, ecco molte altre eccellenti opzioni. http://sqlperformance.com/2012/07/t-sql -query/stringhe divise

Puoi leggere di più sulle schede incrociate dinamiche qui. http://www.sqlservercentral.com/articles/Crosstab/65048/

Non capisco davvero cosa c'entri la tabella #STATICFILTER con questo, quindi l'ho semplicemente ignorato.

Assicurati di aver compreso questo codice prima di implementarlo. Gli articoli di riferimento approfondiscono in dettaglio queste tecniche.

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