吐痰CR& LF进入不同的列

时间:2015-01-26 08:36:11

标签: sql-server-2008 function tsql

我遇到一个问题,我有一个存储名称和地址的nvarchar列,但字符串中有CR。我设法追踪显示空白区域的功能。

示例如下

Mr[?]John[?]Spartan[CR][LF]36[?]Kendrick[?]Road[CR][LF]Birmingham[CR][LF]B3[?]7SA[CR][LF][CR][LF]

我发现了很多关于csvs和其他一些解决方案的帖子,这些解决方案分成了我试图复制的不同行但是还没有能够得到任何有用的东西。

最终结果将是4列而不是1。

Address 1       | Address 2        | Address 3  | Address 4
Mr John Spartan | 36 Kendrick Road | Birmingham | B3 7SA

希望我对我的问题已经足够清楚了。

2 个答案:

答案 0 :(得分:0)

如果要转换为列,请尝试此操作。我在查询中编写了逻辑。

DECLARE @STR NVARCHAR(MAX)='Mr[?]John[?]Spartan[CR][LF]36[?]Kendrick[?]Road[CR][LF]Birmingham[CR][LF]B3[?]7SA[CR][LF][CR][LF]'

-- Convert to CSV
 SELECT @STR = LEFT(REPLACE(REPLACE(@STR,'[?]',' '),'[CR][LF]',' , '),
LEN(REPLACE(REPLACE(@STR,'[?]',''),'[CR][LF]',' , ')))

;WITH CTE AS
(
   -- Split to rows and create a row to set default Row_Number()
    SELECT ROW_NUMBER() OVER(ORDER BY (SELECT 0)) RNO,
    LTRIM(RTRIM(Split.a.value('.', 'VARCHAR(100)'))) 'Address' 
    FROM  
    (
         -- To change ',' to any other delimeter, just change ',' before '</M><M>' to your desired one
         SELECT CAST ('<M>' + REPLACE(@STR, ',', '</M><M>') + '</M>' AS XML) AS Data           
    ) AS A 
    CROSS APPLY Data.nodes ('/M') AS Split(a)
)
-- Convert to columns
SELECT 
MIN(CASE WHEN RNO=1 THEN [Address] END) [Address1], 
MIN(CASE WHEN RNO=2 THEN [Address] END) [Address2],
MIN(CASE WHEN RNO=3 THEN [Address] END) [Address3],
MIN(CASE WHEN RNO=4 THEN [Address] END) [Address4] 
FROM CTE 

<强> RESULT

enter image description here

编辑:

如果您从表格中的列中选择字符串,则可以按照以下步骤操作。

样本表

CREATE TABLE #TEMP(STRINGCOL NVARCHAR(MAX))

INSERT INTO #TEMP
SELECT 'Mr[?]John[?]Spartan[CR][LF]36[?]Kendrick[?]Road[CR][LF]Birmingham[CR][LF]B3[?]7SA[CR][LF][CR][LF]'
UNION ALL
SELECT 'Mrs[?]Smith[?]Tisut[CR][LF]12[?]Criss[?]Road[CR][LF]Birmingham[CR][LF]C4[?]6UI[CR][LF][CR][LF]'

<强> QUERY

;WITH CTE AS
(
    -- Since, its splitting to CSV, we need to get a unique id for those items which was in row
    SELECT ROW_NUMBER() OVER(PARTITION BY RNO ORDER BY (SELECT 0)) RNO2,RNO,
    LTRIM(RTRIM(Split.a.value('.', 'VARCHAR(100)'))) 'Address' 
    FROM  
    (
         -- To change ',' to any other delimeter, just change ',' before '</M><M>' to your desired one
        SELECT RNO,CAST ('<M>' + REPLACE(REPLACE(REPLACE(STRINGCOL,'[?]',' '),'[CR][LF]',' , ')
        , ',', '</M><M>') + '</M>' AS XML) AS Data
        FROM
        (
            -- Select Row_Number for each row
            SELECT ROW_NUMBER() OVER(ORDER BY (SELECT 0)) RNO, STRINGCOL
            FROM #TEMP
        )TAB   

    ) AS A 
    CROSS APPLY Data.nodes ('/M') AS Split(a)   
)
SELECT  RNO,
MIN(CASE WHEN RNO2=1 THEN [Address] END) [Address1], 
MIN(CASE WHEN RNO2=2 THEN [Address] END) [Address2],
MIN(CASE WHEN RNO2=3 THEN [Address] END) [Address3],
MIN(CASE WHEN RNO2=4 THEN [Address] END) [Address4] 
FROM CTE 
GROUP BY RNO

enter image description here

答案 1 :(得分:0)

与@SarathAvanavu类似,但使用PIVOT;

declare @table table (id int not null, NameAndAddress varchar(max) not null)

insert @table values (1, 'Mr John Spartan|36 Kendrick Road|Birmingham|B3 7SA')
insert @table values (2, 'Mrs Victoria Smith|72 Domino Avenue|Leicester|LE1 7RE')
insert @table values (3, 'Miss Sarah Parker|48 Lilly Lane|Bedford|BE2 6TE')

; with cte as (
    select
        id,
        cast('<column>' + replace(NameAndAddress, '|', '</column><column>') + '</column>' as xml) as XmlNameAndAddress
    from
        @table
)
select id, [1] as Column1, [2] as Column2, [3] as Column3, [4] as Column4
from
(
select
    id,
    row_number() over(partition by id order by (select 0)) as rn,
    Split.a.value('.', 'varchar(1024)') as Value
from
    cte
        cross apply XmlNameAndAddress.nodes ('/column') as Split(a)
) AS SourceTable
pivot
(
    min(Value)
    for rn in  ([1], [2], [3], [4])
) as PivotTable