SQL数据透视表

时间:2009-11-03 19:26:54

标签: sql sql-server tsql pivot

我有一个包含以下数据的SQL视图:

ID   ClassName    Description   Flags
1    Class1         Desc1        F1
2    Class1         Desc1        F2
3    Class1         Desc1        F3
4    Class1         Desc1        F4
5    Class2         Desc2        F2
6    Class2         Desc2        F6
7    Class3         Desc3        F1
8    Class4         Desc4        F8

我想要的结果是这样的:

ClassName    Description    F1   F2  F3  F4  F6   F8
Class1         Desc1         T    T  T    T   F   F
Class2         Desc2         F    T  F    F   T   F
Class3         Desc3         T    F  F    F   F   F
Class4         Desc4         F    F  F    F   F   T

我试图查找Pivot示例,但所有这些示例都是SUM或其他聚合函数。不确定这些是否会起作用,因为我没有这样做。

4 个答案:

答案 0 :(得分:1)

Henry Fao走在正确的轨道上 - 但你必须用一组来“压平”行。

select ClassName as ClassName, Description as Description 
   , coalesce(max(F1), 'F') as F1
   , coalesce(max(F2), 'F') as F2
   , etc
 from (
        select classname, description
           , case when flags = 'F1' then 'T' else null end as F1
           , case when flags = 'F2' then 'T' else null end as F2
           etc.
        from tbl
       ) as t
  group by ClassName, Description

每组的F1栏中只应有一个'T'。其他行在T1列中将为空。 max()函数忽略空值并返回'T' - 如果有的话。

答案 1 :(得分:0)

选择classname,description,case当flags ='F1'然后'T',否则'F'结束F1,当flags ='F2'然后'T',否则'F'结束F2,...

答案 2 :(得分:0)

我相信MS SQL Server支持枢轴表,但我不确定如何做到这一点。当我必须在MySQL中转移数据时,我使用Sum和Case。但是,只有当您事先知道列名称时才会有效。这是我可能会这样做的:

Select
X.ClassName,
X.Description,
Case When X.F1 = 1 Then 'T' Else 'F' End As `F1`,
Case When X.F2 = 1 Then 'T' Else 'F' End As `F2`
/* etc. for the rest of your Flags*/
FROM (
    Select
    ClassName,
    Description,
    Sum(Case When Flags = 'F1' Then 1 Else 0 End) As `F1`,
    Sum(Case When Flags = 'F2' Then 1 Else 0 End) As `F2`
    /* etc. for the rest of your Flags*/
    From 
    ClassTable
    Group By
    ClassTable.ClassName
    ) X

在上面的代码中,子查询将产生你想要的输出,除了你得到1和0(假设你从不重复一个类的标志)。语句顶部的“主”查询只是将1和0分为T和F。

同样,这需要您知道您的列名称是什么,但这是我知道如何在没有将“PIVOT”内置到您正在使用的SQL语言的情况下执行此操作的唯一方法。 MS SQL可能内置了PIVOT,因此您可能需要挖掘才能找到它。

答案 3 :(得分:0)

这不是很漂亮,我一般不喜欢动态创建的SQL,但是有一个未知的标志列表,我不确定你会怎么做。另外,你是对的,因为PIVOT命令需要一个聚合,所以我只使用了MAX。是的,这是一种hackish,但它确实完成了工作,并将随着新标志的添加而扩展。我认为这应该适用于2005/2008版本的SQL-SERVER。我不确定2003年,因为我不知道它是否有XML PATH命令。<​​/ p>

Declare @ColumnsIn varchar(max)
Declare @ColumnsIsNull varchar(max)
Declare @sql varchar(max)

Select @ColumnsIn = Stuff((Select Distinct ',[' + Flags + ']' From Classes For XML PATH('')),1,1,'')
Select @ColumnsIsNull = Stuff((Select Distinct ', IsNull([' + Flags + '], ''F'') as [' + Flags + ']' From Classes For XML PATH('')),1,1,'')

Set @sql = '
    Select 
        ClassName,
        Description,
        ' + @ColumnsIsNull + '
    FROM
    (
        Select
            Classes.ClassName,
            Classes.Description,
            Classes.Flags,
            ''T'' as HasFlag
        From
            Classes
    ) as Sub1
    Pivot (Max(HasFlag) For Flags in (' + @ColumnsIn + ')) as Sub2'

Execute(@sql)