【问题标题】:SQL Server 2008 R2 Dynamic Pivot Query with bit types具有位类型的 SQL Server 2008 R2 动态数据透视查询
【发布时间】:2015-04-13 20:39:48
【问题描述】:

我有四个表,其中包含用作输出的一部分的数据,这些数据将在下面定义

[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

注意事项:

  1. IsFinish 将显示 0/1
  2. TypeName1,TypeName2,TypeNameN是[Type].TypeName的文本值
  3. 结果仅过滤到 [Type].IsWorkflow = 1 的位置。
  4. 这是在 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    

关于输出样本的说明:

  1. “C 型”列未列出,因为 IsWorkflow = 0
  2. “类型 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

这种语法有很多问题:

  1. Pivot 似乎想要一个聚合汇总函数,而不是只显示显示值
  2. 列名需要静态,不支持通配符。

我的问题:

  1. PIVOT 是我想要完成的任务的正确选择吗?如果是这样,我应该如何更新我的语法?
  2. 什么是更好的方法?

【问题讨论】:

  • 您是否可以编辑以包含每个表的一些示例数据和最终所需的结果?更好地创建一个 sql fiddle。
  • @bluefeet,我添加了示例数据和输出。

标签: sql-server sql-server-2008 tsql pivot


【解决方案1】:

您可以使用Dynamic Crosstab 执行此操作。请参阅 Jeff Moden 的这个伟大的 article 以供参考。

SQL Fiddle

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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-29
    • 1970-01-01
    • 1970-01-01
    • 2015-02-28
    • 1970-01-01
    相关资源
    最近更新 更多