2016-12-13 66 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

非常感謝!這完美的作品! –