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

Mở và tách các cột động SQL Server 2012

Bạn chỉ cần tách các cột sau khi thực hiện UNPIVOT một cái gì đó như thế này:

WITH Unpivoted 
AS
(
    SELECT region, lob, columns, value
    FROM Regions
    UNPIVOT
    (
       columns
       FOR value IN([GWP 2013] , [GWP 2014] ,
                    [LR 2013]  , [LR 2014] ,
                    [GWP 2015], [LR 2015])
    ) AS u
) 
SELECT 
  region, 
  lob,
  columns,
  CAST(CASE WHEN value LIKE 'GWP%' THEN REPLACE(value,'GWP ', '')
       WHEN value LIKE 'LR%' THEN REPLACE(value,'LR ', '')
  END AS INT) AS Year,
  CASE WHEN value LIKE 'GWP%' THEN 'GWP'
       WHEN value LIKE 'LR%' THEN 'LR'
  END AS Metrics
FROM Unpivoted;

Và sau đó, tất nhiên bạn nên thực hiện động để tránh liệt kê các cột theo cách thủ công và thực hiện động:

DECLARE @cols AS NVARCHAR(MAX);
DECLARE @query AS NVARCHAR(MAX);

select @cols = STUFF((SELECT distinct ',' +
                        QUOTENAME(column_name)
                      FROM information_schema.columns
                      WHERE table_name = 'Regions'
                        AND COLUMN_NAME <> 'Region' 
                        AND COLUMN_NAME <> 'LOB'
                      FOR XML PATH(''), TYPE
                     ).value('.', 'NVARCHAR(MAX)') 
                        , 1, 1, '');


SELECT @query = 'WITH Unpivoted 
                AS
                (
                    SELECT region, lob, columns, value
                    FROM Regions
                    UNPIVOT
                    (
                       columns
                       FOR value IN('+ @cols + ')
                    ) AS u
                ) 
                SELECT 
                  region, 
                  lob,
                  columns,
                  CAST(CASE WHEN value LIKE ''GWP%'' THEN REPLACE(value,''GWP '', '''')
                       WHEN value LIKE ''LR%'' THEN REPLACE(value,''LR '', '''')
                  END AS INT) AS Year,
                  CASE WHEN value LIKE ''GWP%'' THEN ''GWP''
                       WHEN value LIKE ''LR%'' THEN ''LR''
                  END AS Metrics
                FROM Unpivoted';


EXECUTE(@query);

Điều này sẽ hoạt động tốt nếu giả sử rằng:

  • Tất cả các cột [GWP 2013] , [GWP 2014] , [LR 2013] , [LR 2014] , [GWP 2015], [LR 2015], ... etc có cùng định dạng (GWP hoặc LR, sau đó là dấu cách rồi đến năm và
  • Tất cả các cột có cùng kiểu dữ liệu int hoặc thập phân, nếu các kiểu dữ liệu không giống nhau, bạn nên chuyển tất cả chúng thành một kiểu dữ liệu trước khi thực hiện unpivot nếu không bạn sẽ gặp lỗi.

  • SQL Fiddle Demo

Điều này sẽ cung cấp cho bạn:

| region |     lob |  columns | Year | Metrics |
|--------|---------|----------|------|---------|
|  North | Workers |  38902.5 | 2013 |     GWP |
|  North | Workers | 37972404 | 2014 |     GWP |
|  North | Workers |       70 | 2015 |     GWP |
|  North | Workers |       89 | 2013 |      LR |
|  North | Workers |       82 | 2014 |      LR |
|  North | Workers |       80 | 2015 |      LR |

Cập nhật:

Tôi đã sử dụng FOR XML PATH('') .. để nối tất cả danh sách các giá trị trong một chuỗi, đó là một công việc xung quanh trong SQL Server để làm điều đó. Giá trị của @cols sẽ là chuỗi:[GWP 2013], [GWP 2014], ... .

Nếu kiểu dữ liệu trường của bạn khác, bạn phải thực hiện ép kiểu của tất cả các cột sẽ được bỏ phân chia trong truy vấn liên kết trước khi thực hiện UNPVOT như thế này:

SELECT @query = 'WITH Unpivoted 
                AS
                (
                    SELECT region, lob, columns, value
                    FROM 
                    (
                       SELECT 
                         region,
                         lob,
                         CAST([GWP 2013] AS DECIMAL(10,2)) AS [GWP 2013],
                         CAST([GWP 2014] AS DECIMAL(10,2)) AS [GWP 2014],
                         ... etc
                       FROM Regions
                    ) AS t
                    UNPIVOT
                    (
                       columns
                       FOR value IN('+ @cols + ')
                    ) AS u
                ) 
                SELECT 
                  region, 
                  lob,
                  columns,
                  CAST(CASE WHEN value LIKE ''GWP%'' THEN REPLACE(value,''GWP '', '''')
                       WHEN value LIKE ''LR%'' THEN REPLACE(value,''LR '', '''')
                  END AS INT) AS Year,
                  CASE WHEN value LIKE ''GWP%'' THEN ''GWP''
                       WHEN value LIKE ''LR%'' THEN ''LR''
                  END AS Metrics
                FROM Unpivoted';

Nếu bạn cảm thấy khó khăn khi viết truyền cho tất cả các cột theo cách thủ công, bạn có thể tạo động và nối nó thay thế, ví dụ:

DECLARE @colsCasted AS NVARCHAR(MAX);

select @colsCasted = STUFF((SELECT distinct ',' +
                        'CAST(' + QUOTENAME(column_name) + 'AS DECIMAL(10,2)) AS ' + QUOTENAME(column_name)
                      FROM information_schema.columns
                      WHERE table_name = 'Regions'
                        AND COLUMN_NAME <> 'Region' 
                        AND COLUMN_NAME <> 'LOB'
                      FOR XML PATH(''), TYPE
                     ).value('.', 'NVARCHAR(MAX)') 
                        , 1, 1, '');

Sau đó, trong truy vấn động, hãy nối giá trị đó vào nó:

SELECT @query = 'WITH Unpivoted 
                    AS
                    (
                        SELECT region, lob, columns, value
                        FROM 
                        (
                          SELECT region, lob,
                          ' + @colsCasted + '
                          FROM Regions
                        ) AS t
                        UNPIVOT
                        (
                           columns
                           FOR value IN('+ @cols + ')
                        ) AS u
                    ) 
                    SELECT 
                      region, 
                      lob,
                      columns,
                      CAST(CASE WHEN value LIKE ''GWP%'' THEN REPLACE(value,''GWP '', '''')
                           WHEN value LIKE ''LR%'' THEN REPLACE(value,''LR '', '''')
                      END AS INT) AS Year,
                      CASE WHEN value LIKE ''GWP%'' THEN ''GWP''
                           WHEN value LIKE ''LR%'' THEN ''LR''
                      END AS Metrics
                    FROM Unpivoted';


    EXECUTE(@query);



  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óa dữ liệu phân cấp trong bảng SQL

  2. Thêm biểu tượng cảm xúc / biểu tượng cảm xúc vào bảng SQL Server

  3. Tổng quan về nén dữ liệu trong SQL Server

  4. Sự cố truy vấn vùng tên Xml của SQL Server

  5. Làm tròn DateTime không mong muốn trong SQL Server