2016-02-29 121 views
2

我被困在下面左邊的表結構(SQL Server 2012中),以創建一個視圖或函數,將輸出右表中的截圖:TSQL - 創建基於表格的行和單元格值視

Input and Output

TestOutput表包含數據開始ROWNUMBER 10(Step0_Name1)每ID。在真實場景中,我列出的步驟多於此處的示例。

我希望的一些邏輯的名字/號碼識別或行編號,以獲得書面艾克Step0_Name1Step0_Name1_Status所有對吧。

我猜遊標將需要創建某種循環邏輯。

創建測試:

CREATE TABLE [dbo].[Test](
    [ID] [nchar](5) NOT NULL, 
    [Version] [smallint] NOT NULL, 
    [RowNumber] [int] NOT NULL, 
    [COLUMN1] [nvarchar](max) NULL, 
    [COLUMN2] [nvarchar](max) NULL, 
    [COLUMN3] [nvarchar](max) NULL, 
    [COLUMN4] [numeric](15, 3) NULL, 
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED 
( [ID] ASC, 
    [RowNumber] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] 

插入測試:

INSERT INTO [dbo].[Test] 
      ([ID] ,[Version] ,[RowNumber],[COLUMN1],[COLUMN2],[COLUMN3],[COLUMN4]) 
Values 
('00010',1, 1, 'Sheet', 'Part',    'A',   NULL), 
('00010',1, 2, 'Sheet', 'Name',    'PartName',  NULL), 
('00010',1, 3, 'Sheet', 'Price',   NULL,   1.470), 
('00010',1, 4, 'Sheet', 'Step0_SOP',  '2015 CW 09', NULL), 
('00010',1, 5, 'Sheet', 'Step1_SOP',  '2015 CW 10', NULL), 
('00010',1, 6, 'Sheet', 'Step2_SOP',  '2015 CW 11', NULL), 
('00010',1, 7, 'Sheet', 'Step0_Status',  'pending',  NULL), 
('00010',1, 8, 'Sheet', 'Step1_Status',  'frozen',  NULL), 
('00010',1, 9, 'Sheet', 'Step2_Status',  'released',  NULL), 
('00010',1, 10,'Sheet', 'Step0_Name1',  'Auser',  NULL), 
('00010',1, 11,'Sheet', 'Step0_Name2',  NULL,   NULL), 
('00010',1, 12,'Sheet', 'Step0_Name3',  'Buser',  NULL), 
('00010',1, 13,'Sheet', 'Step0_Name1_Status','started',  NULL), 
('00010',1, 14,'Sheet', 'Step0_Name2_Status',NULL,   NULL), 
('00010',1, 15,'Sheet', 'Step0_Name3_Status','pending',  NULL), 
('00010',1, 16,'Sheet', 'Step1_Name1',  'Wuser',  NULL), 
('00010',1, 17,'Sheet', 'Step1_Name2',  'Cuser',  NULL), 
('00010',1, 18,'Sheet', 'Step1_Name3',  'Duser',  NULL), 
('00010',1, 19,'Sheet', 'Step1_Name1_Status','released', NULL), 
('00010',1, 20,'Sheet', 'Step1_Name2_Status','pending',  NULL), 
('00010',1, 21,'Sheet', 'Step1_Name3_Status','released', NULL), 

('00020',1, 1, 'Sheet', 'Part',    'B',   NULL), 
('00020',1, 2, 'Sheet', 'Name',    'PartName',  NULL), 
('00020',1, 3, 'Sheet', 'Price',   NULL,   2.190), 
('00020',1, 4, 'Sheet', 'Step0_SOP',  '2016 CW 19', NULL), 
('00020',1, 5, 'Sheet', 'Step1_SOP',  '2016 CW 20', NULL), 
('00020',1, 6, 'Sheet', 'Step2_SOP',  '2015 CW 21', NULL), 
('00020',1, 7, 'Sheet', 'Step0_Status',  'released',  NULL), 
('00020',1, 8, 'Sheet', 'Step1_Status',  'frozen',  NULL), 
('00020',1, 9, 'Sheet', 'Step2_Status',  'pending',  NULL), 
('00020',1, 10,'Sheet', 'Step0_Name1',  'Xuser',  NULL), 
('00020',1, 11,'Sheet', 'Step0_Name2',  NULL,   NULL), 
('00020',1, 12,'Sheet', 'Step0_Name3',  'Wuser',  NULL), 
('00020',1, 13,'Sheet', 'Step0_Name1_Status','started',  NULL), 
('00020',1, 14,'Sheet', 'Step0_Name2_Status',NULL,   NULL), 
('00020',1, 15,'Sheet', 'Step0_Name3_Status','pending',  NULL), 
('00020',1, 16,'Sheet', 'Step1_Name1',  'Auser',  NULL), 
('00020',1, 17,'Sheet', 'Step1_Name2',  'Cuser',  NULL), 
('00020',1, 18,'Sheet', 'Step1_Name3',  'Buser',  NULL), 
('00020',1, 19,'Sheet', 'Step1_Name1_Status','frozen',  NULL), 
('00020',1, 20,'Sheet', 'Step1_Name2_Status','pending',  NULL), 
('00020',1, 21,'Sheet', 'Step1_Name3_Status','released', NULL) 

創建TestOutput:

CREATE TABLE [dbo].[TestOutput](
    [ID] [nchar](5) NOT NULL, 
    [StepCount] [int] NULL 
    [StepNo] [int] NULL, 
    [Name] [nvarchar](max) NULL, 
    [Status] [nvarchar](max) NULL 
    ) 

可惜sqlfiddle.com所以我貼在這裏的模式拋出一個錯誤

插入測試輸出:

INSERT INTO [dbo].[TestOutput] ([ID] ,[StepCount] ,[StepNo],[Name],[Status]) 
Values 
('00010',1, 0, 'Auser', 'started'), 
('00010',2, 0, NULL, NULL), 
('00010',3, 0, 'Buser', 'pending'), 
('00010',1, 1, 'Wuser', 'released'), 
('00010',2, 1, 'Cuser', 'pending'), 
('00010',3, 1, 'Duser', 'released'), 

('00020',1, 0, 'Xuser', 'started'), 
('00020',2, 0, NULL, NULL), 
('00020',3, 0, 'Wuser', 'pending'), 
('00020',1, 1, 'Auser', 'frozen'), 
('00020',2, 1, 'Cuser', 'pending'), 
('00020',3, 1, 'Buser', 'released') 

我希望你能告訴我如何解決這個問題。

非常感謝。

回答

1

沒有必要光標。

你能先取得StepNo,然後使用窗口函數計算StepCount並加入結果:

SELECT s1.ID, 
     s1.StepCount, 
     s1.StepNo, 
     [Name]  = s1.Column3, 
     [Status] = s2.Column3 
FROM (SELECT *, 
     [StepCount] = ROW_NUMBER() OVER (PARTITION BY ID, StepNo ORDER BY RowNumber) 
     FROM (SELECT *, 
       [StepNo] = SUBSTRING(Column2, 5, CHARINDEX('_', Column2)-5) 
      FROM Test 
      WHERE Column2 LIKE 'Step%_Name%' 
       AND Column2 NOT LIKE '%Status') AS sub) AS s1 
JOIN (SELECT *, 
     [StepCount] = ROW_NUMBER() OVER (PARTITION BY ID, StepNo ORDER BY RowNumber) 
     FROM (SELECT *, 
      [StepNo] = SUBSTRING(Column2, 5, CHARINDEX('_', Column2)-5) 
      FROM Test 
      WHERE Column2 LIKE 'Step%_Name%_Status') AS sub) AS s2 
    ON s1.ID = s2.ID 
AND s1.StepCount = s2.StepCount 
AND s1.StepNo = s2.StepNo 
ORDER BY ID, StepNo, StepCount; 

LiveDemo

輸出:

╔═══════╦═══════════╦════════╦═══════╦══════════╗ 
║ ID ║ StepCount ║ StepNo ║ Name ║ Status ║ 
╠═══════╬═══════════╬════════╬═══════╬══════════╣ 
║ 00010 ║   1 ║  0 ║ Auser ║ started ║ 
║ 00010 ║   2 ║  0 ║  ║   ║ 
║ 00010 ║   3 ║  0 ║ Buser ║ pending ║ 
║ 00010 ║   1 ║  1 ║ Wuser ║ released ║ 
║ 00010 ║   2 ║  1 ║ Cuser ║ pending ║ 
║ 00010 ║   3 ║  1 ║ Duser ║ released ║ 
║ 00020 ║   1 ║  0 ║ Xuser ║ started ║ 
║ 00020 ║   2 ║  0 ║  ║   ║ 
║ 00020 ║   3 ║  0 ║ Wuser ║ pending ║ 
║ 00020 ║   1 ║  1 ║ Auser ║ frozen ║ 
║ 00020 ║   2 ║  1 ║ Cuser ║ pending ║ 
║ 00020 ║   3 ║  1 ║ Buser ║ released ║ 
╚═══════╩═══════════╩════════╩═══════╩══════════╝ 

與CTE相同:

;WITH cte_name AS 
(
    SELECT *, 
     [StepCount] = ROW_NUMBER() OVER (PARTITION BY ID, StepNo ORDER BY RowNumber) 
    FROM (SELECT *, 
      [StepNo] = SUBSTRING(Column2, 5, CHARINDEX('_', Column2)-5) 
     FROM #Test 
     WHERE Column2 LIKE 'Step%_Name%' 
     AND Column2 NOT LIKE '%Status') AS sub 
), cte_status AS 
(
    SELECT *, 
     [StepCount] = ROW_NUMBER() OVER (PARTITION BY ID, StepNo ORDER BY RowNumber) 
    FROM (SELECT *, 
      [StepNo] = SUBSTRING(Column2, 5, CHARINDEX('_', Column2)-5) 
     FROM #Test 
     WHERE Column2 LIKE 'Step%_Name%_Status') AS sub 
) 
SELECT s1.ID, 
     s1.StepCount, 
     s1.StepNo, 
     [Name]  = s1.Column3, 
     [Status] = s2.Column3 
FROM cte_name s1 
JOIN cte_status s2 
    ON s1.ID = s2.ID 
AND s1.StepCount = s2.StepCount 
AND s1.StepNo = s2.StepNo 
ORDER BY ID, StepNo, StepCount; 
+1

太棒了。這比我之前的聲明要快得多:-)非常感謝。 – ratanmalko

1

試試這個:

select 
    t.id 
    ,row_number() over(
    partition by t.id, 
        substring(t.column2, 1, charindex('_', t.column2)) 
    order by t.column2 
) StepCount 
    ,substring(t.column2, 5, charindex('_', t.column2) - 5) [StepNo] 
    ,t.column3 [Name] 
    ,(
    select 
     t1.column3 
    from 
     @test t1 
    where 
     t.column2 + '_Status' = t1.column2 
     and t1.id = t.id 
) [Status] 
from 
    @test t 
where 
    t.column2 like 'step[0-9]_name[0-9]' 
;