sql >> Databáze >  >> RDS >> Sqlserver

Nahrazení abecedy na nulu v libovolném daném řetězci v SQL

K tomu je zapotřebí řada poněkud pokročilých technik v kombinaci. První problém je, že máte oddělená data. To porušuje 1NF, když do jedné buňky nacpete více hodnot. Druhým kouskem skládačky je, jak tato data PIVOTOVAT do dynamického počtu sloupců. Většina lidí kolem SO preferuje použití dynamického PIVOTu. Raději místo toho používám dynamickou křížovou kartu. Zdá se mi, že syntaxe je méně tupá a je dokonce o něco výkonnější než dynamická křížová karta.

O rozdělovači, který obvykle používám, si můžete přečíst zde. http://www.sqlservercentral.com/articles/Tally+Table/72993/ Hlavní výhodou tohoto rozdělovače, kterou většina ostatních nenabízí, je to, že vrací číslo řádku položky v seznamu hodnot. To je pro tento typ situace neuvěřitelně užitečné. Pokud se opravdu chcete ponořit do světa splitterů, je zde několik dalších vynikajících možností. http://sqlperformance.com/2012/07/t-sql -dotazy/rozdělené-řetězce

Více o dynamických křížových kartách si můžete přečíst zde. http://www.sqlservercentral.com/articles/Crosstab/65048/

Opravdu nechápu, co s tím má tabulka #STATICFILTER společného, ​​takže jsem to prostě ignoroval.

Ujistěte se, že tomuto kódu rozumíte, než jej implementujete. Odkazované články jdou o těchto technikách do velkých podrobností.

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



  1. SQL Injection na BadStore

  2. Vyberte datum z časového razítka v SQLAlchemy

  3. Převod období PHP na jednotlivá data MYSQL

  4. Vytvořte sloupec automatického zvýšení v SQLite