使用定界符将字符串拆分为两列 ->
Split string into two columns with delimiter ->
我将以下给定的字符串拆分为给定的 From
和 To
格式的两列。
给定的字符串:
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 添加到该位置
我将以下给定的字符串拆分为给定的 From
和 To
格式的两列。
给定的字符串:
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 添加到该位置