TSQL - 基于 table 行和单元格值创建视图
TSQL - Create view based on table rows and cell values
我坚持使用左下方 table 结构(SQL Server 2012)来创建一个将在屏幕截图中输出右侧 table 的视图或函数:
TestOutput table 包含以 RowNumber 10 (Step0_Name1) 开头的数据,每个 编号。在实际场景中,步骤比我在此处作为示例列出的要多。
我希望有一些逻辑可以让所有对都写成 lke Step0_Name1 和 Step0_Name1_Status通过 name/number 识别或行编号。
我猜测将需要游标来创建某种循环逻辑。
不幸的是 sqlfiddle.com 抛出一个错误,所以我将架构粘贴到这里:
创建测试:
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)
创建测试输出:
CREATE TABLE [dbo].[TestOutput](
[ID] [nchar](5) NOT NULL,
[StepCount] [int] NULL
[StepNo] [int] NULL,
[Name] [nvarchar](max) NULL,
[Status] [nvarchar](max) NULL
)
插入测试输出:
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')
我希望你能告诉我如何解决这个问题。
非常感谢。
试试这个:
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]'
;
不需要游标
您可以先得到 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;
输出:
╔═══════╦═══════════╦════════╦═══════╦══════════╗
║ 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;
我坚持使用左下方 table 结构(SQL Server 2012)来创建一个将在屏幕截图中输出右侧 table 的视图或函数:
TestOutput table 包含以 RowNumber 10 (Step0_Name1) 开头的数据,每个 编号。在实际场景中,步骤比我在此处作为示例列出的要多。
我希望有一些逻辑可以让所有对都写成 lke Step0_Name1 和 Step0_Name1_Status通过 name/number 识别或行编号。
我猜测将需要游标来创建某种循环逻辑。
不幸的是 sqlfiddle.com 抛出一个错误,所以我将架构粘贴到这里:
创建测试:
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)
创建测试输出:
CREATE TABLE [dbo].[TestOutput](
[ID] [nchar](5) NOT NULL,
[StepCount] [int] NULL
[StepNo] [int] NULL,
[Name] [nvarchar](max) NULL,
[Status] [nvarchar](max) NULL
)
插入测试输出:
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')
我希望你能告诉我如何解决这个问题。
非常感谢。
试试这个:
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]'
;
不需要游标
您可以先得到 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;
输出:
╔═══════╦═══════════╦════════╦═══════╦══════════╗
║ 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;