T-SQL:清理数据,将行合并到列中

时间:2017-05-14 14:03:40

标签: sql-server recursion

我试图清理SQL Server中的一些Active Directory数据。我已设法将原始LFD文件读入表中。现在我需要清理一些值,这些属性的值分散在多行上。我可以通过具有前导空格的事实来识别需要附加到先前记录的记录。

示例:

ID        Record                     IsPartOfPrior
3114      memberOf:                        0
3115       CN=Sharepoint-Members-home      1
3116      memberOf:                        0
3117       This is                         1
3118       part of the                     1
3119       next line.                      1

最后,我想生成下表:

ID          Record
3114        memberOf:CN=Sharepoint-Members-home
3116        memberOf:This is part of the next line

我可以通过游标,设置变量,使用临时表和填充表来编写它。但是必须有一套基于(可能是递归?)的方法吗?

我可以使用STUFF方法将各行组合在一起,但是我如何将各种组合在一起呢?我认为我首先必须为每条记录定义groupID,然后按groupID将它们组合在一起?

感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

批评,下面有评论。应该从 SQL Server 2008 开始。

--Here I emulate your table
DECLARE @yourtable TABLE (ID int, Record nvarchar(max), IsPartOfPrior bit)

INSERT INTO @yourtable VALUES                   
(3114,'memberOf:',0),(3115,'CN=Sharepoint-Members-home',1),(3116,'memberOf:',0),(3117,'This is',1),(3118,'part of the',1),(3119,'next line.',1)

--Getting max ID
DECLARE @max_id int 

SELECT @max_id = MAX(ID)+1
FROM @yourtable

--We get next prior for each prior record
--And use STUFF and FOR XML PATH to build new Record
SELECT  y.ID,
        y.Record + b.Record as Record
FROM @yourtable y
OUTER APPLY (
        SELECT TOP 1 ID as NextPrior
        FROM @yourtable 
        WHERE IsPartOfPrior = 0 and y.ID < ID
        ORDER BY ID ASC
    ) as t
OUTER APPLY (
    SELECT STUFF((
        SELECT ' '+Record
        FROM @yourtable
        WHERE ID > y.ID and ID < ISNULL(t.NextPrior,@max_id)
        ORDER BY id ASC
        FOR XML PATH('')
            ),1,1,'') as Record
) as b
WHERE y.IsPartOfPrior = 0

输出:

ID          Record
----------- -----------------------------------------
3114        memberOf:CN=Sharepoint-Members-home
3116        memberOf:This is part of the next line.

如果ID是数字和升序,这将有效。

答案 1 :(得分:0)

另一个选项如果2012 +

示例

Declare @YourTable Table ([ID] int,[Record] varchar(50),[IsPartOfPrior] int)
Insert Into @YourTable Values
 (3114,'memberOf:',0)
,(3115,'CN=Sharepoint-Members-home',1)
,(3116,'memberOf:',0)
,(3117,'This is',1)
,(3118,'part of the',1)
,(3119,'next line.',1)

;with cte as (
    Select *,Grp = sum(IIF([IsPartOfPrior]=0,1,0)) over (Order By ID)
     From @YourTable
)
Select ID
      ,Record  = Stuff((Select ' ' +Record From cte Where Grp=A.Grp Order by ID For XML Path ('')),1,1,'') 
 From (Select Grp,ID=min(ID)from cte Group By Grp   ) A

<强>返回

ID      Record
3114    memberOf: CN=Sharepoint-Members-home
3116    memberOf: This is part of the next line.

如果它有助于可视化,则cte生成:

ID      Record                      IsPartOfPrior   Grp  << Notice Grp Values
3114    memberOf:                   0               1
3115    CN=Sharepoint-Members-home  1               1
3116    memberOf:                   0               2
3117    This is                     1               2
3118    part of the                 1               2
3119    next line.                  1               2