【问题标题】:How to split an Address text column into multiple columns如何将地址文本列拆分为多列
【发布时间】:2014-02-18 21:25:23
【问题描述】:

我有一个文本列,用户可以在其中输入地址。我需要将地址显示/拆分为多列以包含在报告中。

地址数据位于文本列中,并在应用程序/屏幕上如下所示。

123 Stack Street
Holborn
London
EC1 2QW

每个地址行都以回车结束,但在 SQL Server 2008 上显示在一列中。

知道如何在没有复杂代码、变量等的情况下实现这一点吗?

我想在每个回车符处拆分成一个新列。

【问题讨论】:

  • 123 Stack Street (CR) Holborn(CR) London(CR) EC1 2QW (CR)
  • 你试过用谷歌搜索这个吗?甚至查看堆栈溢出?你有什么问题?你试过什么?
  • 搜索 Split Delimited StringParse comma separated string... 唯一棘手的一点是,您的分隔符不是逗号,而是 CHAR(13)
  • 嗨,马特,我用谷歌搜索和谷歌搜索无济于事。大多数可用的解决方案都不符合我的标准,因为他们必须处理 TEXT 列,我想创建一个视图供其他人用于报告。我玩过 CharIndex、PatIndex 但无法让它工作。我希望有一个使用这些与 len 和 substring 的解决方案。

标签: sql sql-server split


【解决方案1】:
CREATE function [dbo].[SplitString] 
(
    @str nvarchar(max), 
    @separator char(1)
)
returns table
AS
return (
with tokens(p, a, b) AS (
    select 
        cast(1 as bigint), 
        cast(1 as bigint), 
        charindex(@separator, @str)
    union all
    select
        p + 1, 
        b + 1, 
        charindex(@separator, @str, b + 1)
    from tokens
    where b > 0
)
select
    p-1 ItemIndex,
    substring(
        @str, 
        a, 
        case when b > 0 then b-a ELSE LEN(@str) end) 
    AS Item
from tokens
);

然后这样执行

select ItemIndex,Item
from SplitString('123 Stack Street
    Holborn
    London
    EC1 2QW',CHAR(13))

【讨论】:

  • 您好,谢谢您,但是我如何对包含地址的列执行此操作?
【解决方案2】:

测试数据

DECLARE @TABLE TABLE ([Address] [VARCHAR](4000))
INSERT INTO @TABLE VALUES
('123' + CHAR(13) + 'Stack Street'+ CHAR(13) + 'Holborn' 
                   + CHAR(13) + 'London'+ CHAR(13) + 'EC1 2QW'),
('456' + CHAR(13) + 'OverFlow Street'+ CHAR(13) + 'Bolton' 
        + CHAR(13) + 'Greater Manchester'+ CHAR(13) + 'M1 6lML')

查询

SELECT * 
FROM
(
SELECT  DENSE_RANK() OVER ( ORDER BY [Address]) AS rn
      ,'Address Line' + CAST(ElementID AS NVARCHAR(10)) AS AddressLines
      , Element
FROM @TABLE
            CROSS APPLY dbo.func_Split([Address], CHAR(13))c
)Q
PIVOT (MAX(Element)
      FOR AddressLines
      IN ([Address Line1],[Address Line2],[Address Line3]
             ,[Address Line4],[Address Line5])
      )p

结果集

╔════╦═══════════════╦═════════════════╦═══════════════╦════════════════════╦═══════════════╗
║ rn ║ Address Line1 ║  Address Line2  ║ Address Line3 ║   Address Line4    ║ Address Line5 ║
╠════╬═══════════════╬═════════════════╬═══════════════╬════════════════════╬═══════════════╣
║  1 ║           123 ║ Stack Street    ║ Holborn       ║ London             ║ EC1 2QW       ║
║  2 ║           456 ║ OverFlow Street ║ Bolton        ║ Greater Manchester ║ M1 6lML       ║
╚════╩═══════════════╩═════════════════╩═══════════════╩════════════════════╩═══════════════╝

拆分函数

我在我的解决方案中使用了拆分函数,请参阅此处了解Sql Server Split function 的定义

【讨论】:

    【解决方案3】:

    我一直更喜欢 xml 并返回到任何其他选项。我还注意到您声明了“TEXT”,所以我继续在执行 REPLACE 的第一个表表达式中为您进行了文本到 varchar(max) 的转换。

    基本上用结束/开始 xml 标记替换所有 CHAR(13)。将其包装在 XML 中。将其输出为 XML。以您认为合适的方式将其切碎回到桌子上。

    DECLARE @Tmp TABLE (Id INT,Name TEXT) 
    INSERT @Tmp SELECT 1,'123 Stack Street' + CHAR(13) + 'Holborn' + CHAR(13) + 'EC1 2QW' 
    
    DECLARE @XML XML = 
    (
        SELECT  T.Id AS "@ID",
              CONVERT(XML,'<PART>' + REPLACE(CAST(Name AS VARCHAR(max)),CHAR(13),'</PART><PART>') + '</PART>') AS AddressParts
        FROM      @Tmp AS T
        FOR XML PATH('Name'), ROOT('Names'), ELEMENTS, TYPE
    )
    
    SELECT  Address1 = FieldAlias.value('(AddressParts/PART)[1]','varchar(max)'),
           Address2 = FieldAlias.value('(AddressParts/PART)[2]','varchar(max)'),
           Address3 = FieldAlias.value('(AddressParts/PART)[3]','varchar(max)'),
           Address3 = FieldAlias.value('(AddressParts/PART)[4]','varchar(max)')
    FROM       @XML.nodes('//Name') AS S(FieldAlias)
    

    【讨论】:

      【解决方案4】:

      如果使用 sql server 2016(问题是 5 年前)或更高版本,那么您有 https://docs.microsoft.com/en-us/sql/t-sql/functions/parsename-transact-sql?view=sql-server-2016 可用。只需将回车符替换为“。”性格第一。每行最多可使用 3-4 个回车符。

      【讨论】:

        猜你喜欢
        • 2020-06-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多