簡體   English   中英

SQL 服務器中的分隔符拆分為單獨的動態列

[英]Delimiter splitting into separate dynamic columns in SQL Server

我知道很多與此相關的問題都可以在 Google 和 SO 中找到,但具體問題不可用,所以在這里尋求偉大的人的幫助。

主要任務是在 SQL 服務器中將單個列的 pipe 分隔值拆分為多個列(值會發生變化,因此需要動態創建列)。

我瀏覽了多個鏈接並了解

  1. 2016 年后, STRING_SPLIT()內置 function 將有助於拆分並顯示在單獨的行中(但我需要顯示在列中)。

  2. [PIVOT] -> PIVOT在 Static 和動態一個中都是可能的,但這對於按行順序排列的數據很有用,使其成為列順序。 但是我的表數據是按列順序排列的,Pipe 分成一列。

  3. XML -> 這也僅限於 static(請參閱我的SQL 小提琴查詢和輸出),並且需要動態創建列而不定義查詢中的列數。

代碼:

CREATE TABLE DELIMTEDPATH
(
    ID int,
    Path varchar(max)
);

INSERT INTO DELIMTEDPATH 
VALUES (1, 'John|Albert|James'),
       (2, 'Cricket'),
       (3, 'Mary|Joseph|Priyanka|Gilbert|Customer|Service|Passenger|MN-1234|MK-5678');`

;WITH SplitMenus AS
(
    SELECT 
        ID, 
        CONVERT(XML, '<MENUS><Menu>' + REPLACE(Path, '|', '</Menu><Menu>') + '</Menu></MENUS>') AS Path
    FROM
        DELIMTEDPATH
    WHERE
        ID IN (1, 2, 3)
)
SELECT
    ID, 
    Path.value('/MENUS[2]/Menu[2]', 'varchar(100)') AS Name1,
    Path.value('/MENUS[2]/Menu[1]', 'varchar(100)') AS Name2,
    Path.value('/MENUS[2]/Menu[3]', 'varchar(100)') AS Name3,
    Path.value('/MENUS[2]/Menu[4]', 'varchar(100)') AS Name4
FROM
    SplitMenus

我得到這個 output:

在此處輸入圖像描述

但是我需要的 output 是動態的,以顯示 ID=3 的所有值。

這是使用 XML、XQuery 和動態 SQL 的解決方案。

SQL

USE tempdb;
GO

-- DDL and sample data population, start
DROP TABLE IF EXISTS DELIMTEDPATH;
CREATE TABLE DELIMTEDPATH (ID INT IDENTITY PRIMARY KEY, [Path] VARCHAR(MAX));

INSERT INTO DELIMTEDPATH ([Path]) VALUES 
('John|Albert|James'),
('Cricket'),
('Mary|Joseph|Priyanka|Gilbert|Customer|Service|Passenger|MN-1234|MK-5678');
-- DDL and sample data population, end

DECLARE @separator CHAR(1) = '|'
    , @CrLf CHAR(2) = CHAR(13) + CHAR(10)
    , @nameCounter INT
    , @i INT = 1;

SET @nameCounter = (SELECT MAX(LEN([Path]) - LEN(REPLACE([Path], @separator,'')))/COALESCE(NULLIF(LEN(@separator), 0), 1) AS cnt
FROM DELIMTEDPATH) + 1;

DECLARE @SQL NVARCHAR(MAX) = 
N';WITH rs AS
(
    SELECT ID, 
        CAST(''<root><r>'' + REPLACE([Path], ''' + @separator + ''', ''</r><r>'') + ''</r></root>'' AS XML) AS xmldata
    FROM DELIMTEDPATH
)
SELECT ID' + @CrLf;

WHILE @i <= @nameCounter BEGIN
    SET @SQL += ', c.value(''(r[' + CAST(@i AS VARCHAR(3)) + ']/text())[1]'', ''VARCHAR(100)'') AS Name' + CAST(@i AS VARCHAR(3)) + @CrLf
    SET @i += 1
END

SET @SQL += 'FROM rs CROSS APPLY xmldata.nodes(''/root'') AS t(c);'

-- just to see it
PRINT @sql;

-- we are ready at this point
EXEC sp_executesql @SQL;

Output

+----+---------+--------+----------+---------+----------+---------+-----------+---------+
| ID |  Name1  | Name2  |  Name3   |  Name4  |  Name5   |  Name6  |   Name7   |  Name8  |
+----+---------+--------+----------+---------+----------+---------+-----------+---------+
|  1 | John    | Albert | James    | NULL    | NULL     | NULL    | NULL      | NULL    |
|  2 | Cricket | NULL   | NULL     | NULL    | NULL     | NULL    | NULL      | NULL    |
|  3 | Mary    | Joseph | Priyanka | Gilbert | Customer | Service | Passenger | MN-1234 |
+----+---------+--------+----------+---------+----------+---------+-----------+---------+

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM