使用定界符将字符串拆分为两列 ->

Split string into two columns with delimiter ->

我将以下给定的字符串拆分为给定的 FromTo 格式的两列。

给定的字符串:

DECLARE @String VARCHAR(MAX) = 'A->B->C->D'

预期结果

From    To
-----------
A       B
B       C
C       D

尝试过:

DECLARE @String VARCHAR(MAX) = 'A->B->C->D' 
SELECT CASE WHEN item LIKE '%-' THEN REPLACE(item,'-','') END AS [From],
       CASE WHEN item NOT LIKE '%-' THEN item END AS [To]   
FROM dbo.f_Split(@String,'>')

试试这个:

DECLARE @String VARCHAR(MAX) = 'A->B->C->D';


DECLARE @StringXML XML = CAST('<a>' + REPLACE(@String, '->', '</a><a>') + '</a>' AS XML);


WITH DataSource ([RowID], [RowValue]) AS
(
    SELECT  ROW_NUMBER() OVER (ORDER BY T.c ASC)
           ,T.c.value('.', 'CHAR(1)')
    FROM @StringXML.nodes('a') T(c)
)
SELECT DS1.[RowValue] AS [From]
      ,DS2.[RowValue] AS [TO]
FROM DataSource DS1
INNER JOIN DataSource DS2
    ON DS1.[RowID] + 1 = DS2.[RowID];

想法是拆分值并对其进行排序。然后只需执行连接到设置为自身的最后一行。

您可以在处理之前 REPLACE 字符串并直接应用联接以获得预期的输出。考虑 dbo.f_Split 函数 returns 列 item

DECLARE @String VARCHAR(MAX) = 'A->B->C->D->E->F->G';

SET @String = REPLACE(@String, '->', '>')

WITH CTE(RowNumber, RowData) AS
(
    SELECT
        ROW_NUMBER() OVER (ORDER BY S1.item) AS RowNumber,
        S1.item AS RowData
    FROM dbo.f_Split(@String,'>') S1
)
SELECT
    C1.RowData AS [From], 
    C2.RowData AS [To]
FROM CTE C1
INNER JOIN CTE C2 ON C1.RowNumber + 1 = C2.RowNumber

使用位置和 +1 的另一种解决方案:

DECLARE @String VARCHAR(MAX) = 'A->B->C->D->E';

DECLARE @YourStringAsXml XML=CAST('<x>' + REPLACE(@String, '->', '</x><x>') + '</x>' AS XML);

--查询

WITH tally(nr) AS 
(
    SELECT TOP (@YourStringAsXml.value('count(/x)','int')) ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
    FROM master..spt_values
)
SELECT @YourStringAsXml.value('/x[sql:column("nr")][1]','varchar(10)') AS FromNode
      ,@YourStringAsXml.value('/x[sql:column("nr")+1][1]','varchar(10)') AS ToNode
FROM tally;

简而言之:

  • 我们将字符串转换为 XML
  • 我们使用带有计算 TOP() 子句的 即时计数 来获取 运行 数字的列表(更好的是 - 和反正很帅 - 一个物理数字table).
  • 现在我们可以根据位置 (sql:column()) 和邻居选择元素,只需将 +1 添加到该位置