2016-02-29 80 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]' 
;