SQL Server 2008 R2 Dynamic Pivot Query with bit types
SQL Server 2008 R2 Dynamic Pivot Query with bit types
我有四个表,其中包含用作下面定义的输出的一部分的数据
[Status]
StatusId INT
IsFinish BIT
[Type]
TypeId INT
TypeName VARCHAR
IsWorkflow BIT
[System]
SystemId INT
SystemName VARCHAR
[Track]
TrackId INT
StatusId INT (FK)
TypeId INT (FK)
SystemId INT (FK)
所需的输出格式如下:
SystemName | TypeName1 | TypeName2 | TypeNameN
SystemName | IsFinish | IsFinish | IsFinish
备注:
- IsFinish 将显示 0/1
- TypeName1、TypeName2、TypeNameN 是 [Type].TypeName
的文本值
- 结果仅过滤到 [Type].IsWorkflow = 1 的位置。
- 这是 运行 SQL Server 2008 R2
这是示例数据:
[Status]
StatusId, IsFinish
10, 1
11, 1
12, 0
[Type]
TypeId, TypeName, IsWorkflow
101, 'Type A', 1
102, 'Type B', 1
103, 'Type C', 0
104, 'Type D', 1
[System]
SystemId, SystemName
1001, 'System 1'
1002, 'System 2'
1003, 'System 3'
[Track]
TrackId, StatusId, TypeId, SystemId
20001, 10, 101, 1001
20002, 10, 102, 1001
20003, 12, 101, 1002
20004, 11, 101, 1003
20005, 10, 102, 1003
20006, 12, 103, 1003
所需的输出样本:
System Name | Type A | Type B
System 1 | 1 | 0
System 2 | 0 | <NULL>
System 3 | 1 | 0
关于输出样本的注释:
- "Type C" 列未列出,因为 IsWorkflow = 0
- "Type D" 列未列出,因为没有曲目具有该类型
我根据我找到的示例尝试了语法:
SELECT T.*
FROM [Type] T INNER JOIN [Track] TR ON T.TypeId = TR.TypeId
INNER JOIN [System] S ON S.SystemId = TR.SystemId
INNER JOIN [Status] ST ON ST.StatusId = TR.StatusId
PIVOT ( IsFinish FOR TypeName IN (*)) AS Workflow
WHERE AND IsWorkflow = 1 AND Status = 11
此语法存在多个问题:
- Pivot 似乎想要一个聚合汇总函数,而不是仅显示值
- 列名需要静态,不支持通配符。
我的问题:
- PIVOT 是我想要实现的目标的正确选择吗?如果是这样,我应该如何更新我的语法?
- 什么是更好的方法?
您可以使用 Dynamic Crosstab
来完成此操作。请参阅 Jeff Moden 的精彩 article 以供参考。
DECLARE @sql1 VARCHAR(4000) = ''
DECLARE @sql2 VARCHAR(4000) = ''
DECLARE @sql3 VARCHAR(4000) = ''
SELECT @sql1 =
'SELECT
s.SystemName' + CHAR(10)
SELECT @sql2 = @sql2 +
' , MAX(CASE WHEN t.TypeId = '+ CONVERT(VARCHAR(5),t.TypeId) + ' THEN CAST(st.IsFinish AS INT) END) AS [' + t.TypeName + '],' + CHAR(10)
FROM(
SELECT t.*
FROM Type t
WHERE
t.IsWorkflow = 1
AND EXISTS(SELECT 1 FROM Track WHERE TypeId = t.TypeId)
)t
SELECT @sql3 =
'FROM System s
INNER JOIN Track t ON t.SystemId = s.SystemId
INNER JOIN Status st ON st.StatusId = t.StatusId
GROUP BY s.SystemName'
PRINT(@sql1 + @sql2 + @sql3)
EXEC(@sql1 + @sql2 + @sql3)
我有四个表,其中包含用作下面定义的输出的一部分的数据
[Status]
StatusId INT
IsFinish BIT
[Type]
TypeId INT
TypeName VARCHAR
IsWorkflow BIT
[System]
SystemId INT
SystemName VARCHAR
[Track]
TrackId INT
StatusId INT (FK)
TypeId INT (FK)
SystemId INT (FK)
所需的输出格式如下:
SystemName | TypeName1 | TypeName2 | TypeNameN
SystemName | IsFinish | IsFinish | IsFinish
备注:
- IsFinish 将显示 0/1
- TypeName1、TypeName2、TypeNameN 是 [Type].TypeName 的文本值
- 结果仅过滤到 [Type].IsWorkflow = 1 的位置。
- 这是 运行 SQL Server 2008 R2
这是示例数据:
[Status]
StatusId, IsFinish
10, 1
11, 1
12, 0
[Type]
TypeId, TypeName, IsWorkflow
101, 'Type A', 1
102, 'Type B', 1
103, 'Type C', 0
104, 'Type D', 1
[System]
SystemId, SystemName
1001, 'System 1'
1002, 'System 2'
1003, 'System 3'
[Track]
TrackId, StatusId, TypeId, SystemId
20001, 10, 101, 1001
20002, 10, 102, 1001
20003, 12, 101, 1002
20004, 11, 101, 1003
20005, 10, 102, 1003
20006, 12, 103, 1003
所需的输出样本:
System Name | Type A | Type B
System 1 | 1 | 0
System 2 | 0 | <NULL>
System 3 | 1 | 0
关于输出样本的注释:
- "Type C" 列未列出,因为 IsWorkflow = 0
- "Type D" 列未列出,因为没有曲目具有该类型
我根据我找到的示例尝试了语法:
SELECT T.*
FROM [Type] T INNER JOIN [Track] TR ON T.TypeId = TR.TypeId
INNER JOIN [System] S ON S.SystemId = TR.SystemId
INNER JOIN [Status] ST ON ST.StatusId = TR.StatusId
PIVOT ( IsFinish FOR TypeName IN (*)) AS Workflow
WHERE AND IsWorkflow = 1 AND Status = 11
此语法存在多个问题:
- Pivot 似乎想要一个聚合汇总函数,而不是仅显示值
- 列名需要静态,不支持通配符。
我的问题:
- PIVOT 是我想要实现的目标的正确选择吗?如果是这样,我应该如何更新我的语法?
- 什么是更好的方法?
您可以使用 Dynamic Crosstab
来完成此操作。请参阅 Jeff Moden 的精彩 article 以供参考。
DECLARE @sql1 VARCHAR(4000) = ''
DECLARE @sql2 VARCHAR(4000) = ''
DECLARE @sql3 VARCHAR(4000) = ''
SELECT @sql1 =
'SELECT
s.SystemName' + CHAR(10)
SELECT @sql2 = @sql2 +
' , MAX(CASE WHEN t.TypeId = '+ CONVERT(VARCHAR(5),t.TypeId) + ' THEN CAST(st.IsFinish AS INT) END) AS [' + t.TypeName + '],' + CHAR(10)
FROM(
SELECT t.*
FROM Type t
WHERE
t.IsWorkflow = 1
AND EXISTS(SELECT 1 FROM Track WHERE TypeId = t.TypeId)
)t
SELECT @sql3 =
'FROM System s
INNER JOIN Track t ON t.SystemId = s.SystemId
INNER JOIN Status st ON st.StatusId = t.StatusId
GROUP BY s.SystemName'
PRINT(@sql1 + @sql2 + @sql3)
EXEC(@sql1 + @sql2 + @sql3)