Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Thay thế các bảng chữ cái thành số 0 trong bất kỳ chuỗi nhất định nào trong SQL

Điều này cần một số kỹ thuật hơi nâng cao kết hợp để thực hiện điều này. Vấn đề đầu tiên là bạn có dữ liệu được phân tách. Điều này vi phạm 1NF khi bạn nhồi nhét nhiều giá trị vào một ô duy nhất. Phần thứ hai của câu đố là làm thế nào để CHUYỂN dữ liệu này thành một số cột động. Hầu hết mọi người xung quanh SO thích sử dụng PIVOT động. Thay vào đó, tôi thích sử dụng một tab chéo động. Tôi thấy cú pháp này ít khó hiểu hơn và nó thậm chí còn hiệu quả hơn một chút so với tab chéo động.

Bạn có thể đọc về bộ chia mà tôi thường sử dụng ở đây. http://www.sqlservercentral.com/articles/Tally+Table/72993/ Ưu điểm chính mà bộ tách này cung cấp mà hầu hết những người khác không có là nó trả về số hàng của mục trong danh sách các giá trị. Điều này cực kỳ hữu ích cho loại tình huống này. Nếu bạn thực sự muốn đi sâu vào thế giới bộ chia, đây là một số lựa chọn tuyệt vời khác. http://sqlperformance.com/2012/07/t-sql -query / split-string

Bạn có thể đọc thêm về Tab chéo động tại đây. http://www.sqlservercentral.com/articles/Crosstab/65048/

Tôi thực sự không hiểu bảng #STATICFILTER có liên quan gì với điều này nên tôi đã bỏ qua nó.

Đảm bảo rằng bạn hiểu mã này trước khi triển khai. Các bài báo tham khảo đi sâu vào chi tiết về các kỹ thuật này.

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. Xác định Chênh lệch múi giờ trong T-SQL

  2. lưu trữ tiếng Ả Rập trong cơ sở dữ liệu SQL

  3. Cách nối hai bảng với nhau có cùng số hàng theo thứ tự của chúng

  4. Việc kết hợp giữa các lượt xem và bảng có thể ảnh hưởng đến hiệu suất không?

  5. SQL Server - xác định cột kiểu XML với mã hóa UTF-8