【问题标题】:SQL Server create rows from custom delimited textSQL Server 从自定义分隔文本创建行
【发布时间】:2019-05-31 16:29:07
【问题描述】:

我要计算航班行程的二氧化碳排放量。航班行程可以包括 1 跳,例如 DXB/CDG,或 ABJ/ADD/BKK/KUL/ADD/ABJ,即 5 跳。我的挑战是我需要将行程信息分解为单个航班信息,因为每次飞行都会计算二氧化碳排放量:

来源ABJ/ADD/BKK/KUL/ADD/ABJ

并将其转换为:

【问题讨论】:

  • 您使用的是哪个数据库?
  • MS SQL Server 2012

标签: sql sql-server tsql split


【解决方案1】:

我会建议这种方法:

DECLARE  @fligth VARCHAR(100)='ABJ/ADD/BKK/KUL/ADD/ABJ';

WITH Casted(flightXML) AS
    (SELECT CAST('<x>' + REPLACE(@fligth,'/','</x><x>') + '</x>' AS XML))
,Tally(Nmbr) AS 
    (SELECT TOP((SELECT flightXML.value('count(/x)','int') FROM Casted)) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values)
SELECT flightXML.value('(/x[sql:column("Nmbr")]/text())[1]','varchar(10)') AS FromAirport
      ,flightXML.value('(/x[sql:column("Nmbr")+1]/text())[1]','varchar(10)') AS ToAirport
FROM Casted
CROSS JOIN Tally
WHERE flightXML.value('(/x[sql:column("Nmbr")+1]/text())[1]','varchar(10)') IS NOT NULL;

想法:

我们通过用标签替换分隔符将分隔字符串转换为 XML。所以我们得到了

<x>ABJ</x>
<x>ADD</x>
<x>BKK</x>
<x>KUL</x>
<x>ADD</x>
<x>ABJ</x>

现在 XQuery 允许 as 按位置检索值。因此,第二个 CTE 创建了一个即时计数。它将返回从到 n 的连续数字,其中 n 是字符串中的停止数。

最终查询将使用sql:column() 将计数号引入XQuery。您可以将其解读为Nmbr 位置找到&lt;x&gt; 并返回其内容。现在在Nmbr+1 位置找到&lt;x&gt;

【讨论】:

  • 我也没有考虑过,这是一个很好的解决方案,可以在不需要函数的情况下分解它
【解决方案2】:

要获得预期结果,您可以创建一个函数,该函数将使用提供的分隔符将字符串拆分为行。之后,您可以根据需要对返回的数据进行进一步调整或应用更改。

第一步:创建函数

CREATE  FUNCTION [dbo].[splitstring] ( @stringToSplit VARCHAR(MAX) ,@Delimiter VARCHAR(10))
RETURNS @returnList TABLE ([Word] [nvarchar] (500))
AS
BEGIN
    DECLARE @name NVARCHAR(255)
    DECLARE @pos INT
    DECLARE @RN INT = 1

    WHILE CHARINDEX(@Delimiter, @stringToSplit) > 0
    BEGIN
        SELECT @pos  = CHARINDEX(@Delimiter, @stringToSplit)  
        SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1)

        INSERT INTO @returnList([Word],RN)
        SELECT @name,@RN

        SET @RN = @RN + 1

        SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)
    END

    INSERT INTO @returnList([Word],RN)
    SELECT @stringToSplit,@RN

RETURN
END

第 2 步:使用该函数获取所需数据

SELECT A.Word+'/'+B.Word FROM
(
    SELECT Word,RN 
    FROM [dbo].[splitstring]('ABJ/ADD/BKK/KUL/ADD/ABJ','/') 
) A
INNER JOIN 
(
    SELECT Word,RN 
    FROM [dbo].[splitstring]('ABJ/ADD/BKK/KUL/ADD/ABJ','/')
)B ON A.RN = B.RN-1

输出将是-

ABJ/ADD
ADD/BKK
BKK/KUL
KUL/ADD
ADD/ABJ

【讨论】:

  • 依赖WHILE 循环的字符串拆分器?严重地?这是 - 嗯 - 缓慢而过时......
  • 这是一个很好的解决方案。感谢您的大力帮助
  • @Robert,不客气。你能接受答案并投赞成票吗?这会激励我。
  • 谢谢@mkRabbani,我已经设法使用这个功能解决了这个问题。我必须使用您的解决方案和下面 Shnugo 的解决方案的混合来填充一个包含所有不同路线的表,然后通过将行程代码传递给函数来计算排放量
  • 不客气。如果真的有帮助,请接受答案。
猜你喜欢
  • 2018-05-14
  • 1970-01-01
  • 2017-03-25
  • 1970-01-01
  • 2017-11-25
  • 2015-03-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多