Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Zamiana alfabetów na zero w dowolnym ciągu w SQL

Aby to zrobić, potrzeba do tego kilku nieco zaawansowanych technik. Pierwszym problemem jest to, że masz rozgraniczone dane. Narusza to 1NF, gdy wpychasz wiele wartości do jednej komórki. Drugim elementem układanki jest przestawianie tych danych na dynamiczną liczbę kolumn. Większość ludzi w SO woli używać dynamicznego PIVOT. Wolę zamiast tego używać dynamicznej karty krzyżowej. Uważam, że składnia jest mniej rozwarta i jest nawet nieco bardziej wydajna niż dynamiczna karta krzyżowa.

O rozgałęźniku, którego zazwyczaj używam, możesz przeczytać tutaj. http://www.sqlservercentral.com/articles/Tally+Table/72993/ Główną zaletą tego rozdzielacza, której większość innych nie oferuje, jest to, że zwraca numer wiersza elementu na liście wartości. Jest to niezwykle przydatne w tego typu sytuacjach. Jeśli naprawdę chcesz zanurzyć się w świecie splitterów, oto kilka innych doskonałych opcji. http://sqlperformance.com/2012/07/t-sql -zapytania/podzielone ciągi

Więcej informacji o dynamicznych zakładkach krzyżowych znajdziesz tutaj. http://www.sqlservercentral.com/articles/Crosstab/65048/

Naprawdę nie rozumiem, co ma z tym wspólnego tabela #STATICFILTER, więc po prostu ją zignorowałem.

Upewnij się, że rozumiesz ten kod, zanim go zaimplementujesz. Wspomniane artykuły szczegółowo opisują te techniki.

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Wykryj przerwy powyżej 30 minut w kolumnie sygnatury czasowej

  2. Dlaczego potrzebujemy usług SSIS i schematu gwiazdy hurtowni danych?

  3. Znajdź kolumny wartości łączność

  4. SQL Server 2005 — numer_wiersza()

  5. wartość kolumny w jednym wierszu