2016-12-13 60 views
1

我正在导入包含多个“报告”的大型文本文件。每个报告由多行数据组成。我知道新报告何时开始的唯一方法是以“XX”开头的行。那么以下所有行都属于具有XX的主行。我试图放入一个分组标识,以便我可以处理数据并将其解析到数据库中。解析文本文件,基于文本字符串标记组的行

CREATE TABLE RawData(
    ID int IDENTITY(1,1) NOT NULL 
    ,Grp1 int NULL 
    ,Grp2 int NULL 
    ,Rowdata varchar(max) NULL 
) 

INSERT INTO RawData(Rowdata) VALUES 'XX Monday' 
INSERT INTO RawData(Rowdata) VALUES 'Tues day' 
INSERT INTO RawData(Rowdata) VALUES 'We d ne s day' 
INSERT INTO RawData(Rowdata) VALUES 'Thurs day' 
INSERT INTO RawData(Rowdata) VALUES 'F r i d day' 
INSERT INTO RawData(Rowdata) VALUES 'XX January' 
INSERT INTO RawData(Rowdata) VALUES 'Feb r u a' 
INSERT INTO RawData(Rowdata) VALUES 'XX Sun d a y' 
INSERT INTO RawData(Rowdata) VALUES 'Sat ur day' 

我需要编写一个脚本,根据“XX”行所在的位置更新Grp1字段。当我完成时,我想看起来像这样的表格:

ID Grp1 Grp2 RowData 
1 1  1  XX Monday 
2 1  2  Tues day 
3 1  3  We d ne s day 
4 1  4  Thurs day 
5 1  5  F r i d day 
6 2  1  XX January 
7 2  2  Feb r u a 
8 3  1  XX Sun d a y 
9 3  2  Sat ur day 

我知道的Grp2字段我可以使用DENSE_RANK。我遇到的问题是如何填写Grp1的所有值。我可以在我看到'XX'的地方做一个更新,但是这并没有填写下面的值。

谢谢你的任何建议/帮助。

回答

0

这应该做的伎俩

-- sample data 
DECLARE @RawData TABLE 
(
    ID int IDENTITY(1,1) NOT NULL 
    ,Grp1 int NULL 
    ,Grp2 int NULL 
    ,Rowdata varchar(max) NULL 
); 
INSERT INTO @RawData(Rowdata) 
VALUES ('XX Monday'),('Tues day'),('We d ne s day'),('Thurs day'),('F r i d day'), 
     ('XX January'),('Feb r u a'),('XX Sun d a y'),('Sat ur day'); 

-- solution 
WITH rr AS 
(
    SELECT ID, thisVal = ROW_NUMBER() OVER (ORDER BY ID) 
    FROM @rawData 
    WHERE RowData LIKE 'XX %' 
), 
makeGrp1 AS 
(
    SELECT 
    ID, 
    Grp1 = (SELECT MAX(thisVal) FROM rr WHERE r.id >= rr.id), 
    RowData 
    FROM @rawData r 
) 
SELECT 
    ID, 
    Grp1, 
    Grp2 = ROW_NUMBER() OVER (PARTITION BY Grp1 ORDER BY ID), 
    RowData 
FROM makeGrp1; 

UPDATE:以下是更新你@RawData表中的代码;我只是重新阅读了这个要求。我要离开原来的解决方案,它可以帮助你了解bbetter我更新是如何工作的:

-- sample data 
DECLARE @RawData TABLE 
(
    ID int IDENTITY(1,1) NOT NULL 
    ,Grp1 int NULL 
    ,Grp2 int NULL 
    ,Rowdata varchar(max) NULL 
); 
INSERT INTO @RawData(Rowdata) 
VALUES ('XX Monday'),('Tues day'),('We d ne s day'),('Thurs day'),('F r i d day'), 
     ('XX January'),('Feb r u a'),('XX Sun d a y'),('Sat ur day'); 

-- Solution to update the @RawData Table 
WITH rr AS 
(
    SELECT ID, thisVal = ROW_NUMBER() OVER (ORDER BY ID) 
    FROM @rawData 
    WHERE RowData LIKE 'XX %' 
), 
makeGroups AS 
(
    SELECT 
    ID, 
    Grp1 = (SELECT MAX(thisVal) FROM rr WHERE r.id >= rr.id), 
    Grp2 = ROW_NUMBER() 
     OVER (PARTITION BY (SELECT MAX(thisVal) FROM rr WHERE r.id >= rr.id) ORDER BY ID) 
    FROM @rawData r 
) 
UPDATE @RawData 
SET Grp1 = mg.Grp1, Grp2 = mg.Grp2 
FROM makeGroups mg 
JOIN @RawData rd ON mg.ID = rd.ID; 
0
;with cte0 as (
    Select *,Flag = case when RowData like 'XX%' then 1 else 0 end 
    From RawData) 
Update RawData 
    Set Grp1 = B.Grp1 
     ,Grp2 = B.Grp2 
From RawData U 
Join (
     Select ID 
       ,Grp1 = Sum(Flag) over (Order by ID) 
       ,Grp2 = Row_Number() over (Partition By (Select Sum(Flag) From cte0 Where ID<=a.ID) Order by ID) 
     From cte0 A 
    ) B on U.ID=B.ID 

Select * from RawData 

的更新RAWDATA看起来像这样

enter image description here

+0

做得好约翰 - 这是一个很有效的解决方案一个小小的更正:你的SET语句中的 ,而不是你想要的Grp2 = B.Grp1 Grp2 = B.Grp2。 –

+0

@AlanBurstein谢谢你的复制错误 –

+0

非常感谢!这完美的作品! –