Sql server SQL Server Management Studio 2012透视/交叉表查询

Sql server SQL Server Management Studio 2012透视/交叉表查询,sql-server,Sql Server,我正在使用SQLServerManagementStudio 2012,希望为超过2300行的表创建透视/交叉表查询 该表有5列: - name - group - status - date - count 大约有580个不同的名字 每个名称与4个不同的组(A、B、C和D)关联 每个组的完整状态为是或否 完成时,日期与每个状态关联。否则,状态为空 计数列仅适用于B组和D组,是一个整数值 样本A: name group status date count A.A.1

我正在使用SQLServerManagementStudio 2012,希望为超过2300行的表创建透视/交叉表查询

该表有5列:

 - name
 - group
 - status
 - date
 - count
大约有580个不同的名字

每个名称与4个不同的组(A、B、C和D)关联

每个组的完整状态为是或否

完成时,日期与每个状态关联。否则,状态为空

计数列仅适用于B组和D组,是一个整数值

样本A:

name    group  status   date    count
A.A.1     A     yes     5/23    NULL
A.A.1     B     yes     5/27    112
A.A.1     C     yes     6/4     NULL
A.A.1     D     yes     6/15    122
A.B.2     A     yes     5/25    NULL
A.B.2     B     yes     6/1     119
A.B.2     C     no      NULL    NULL
A.B.2     D     no      NULL    NULL
我试图将每个名称的状态显示为11列中的字段值:

 - name
 - group A
 - group A date
 - group B
 - group B date
 - group B count
 - group C
 - group C date
 - group D
 - group D date
 - group D count
“name”列将包含580个不同的名称,以及A、B、C和D中相应的组数据

样本B:

nm      grp_A   A_day   grp_B   B_day   B_ct    grp_C   C_day   grp_D   D_day   D_ct
A.A.1   yes     5/23    yes     5/27    112     yes     6/4     yes     6/15    122
A.B.2   yes     5/25    yes     6/1     119     no      NULL    no      NULL    NULL
(已更改列名以适应此问题部分的格式)

最终,结果应在第一列中包含所有580个不同的名称,以及每个组的相应状态、完成日期(如果尚未完成,则为NULL)以及组B和D的计数

我尝试过使用CASE语句,但它会为每个组生成一次名称,导致原始表在11个coulmns之间隔开

样本C:

nm     grp_A    A_day   grp_B   B_day   B_ct    grp_C   C_day   grp_D   D_day   D_ct
A.A.1   yes     5/23                                
A.A.1                    yes    5/27    112         
A.A.1                                             yes   6/4         
A.A.1                                                            yes    6/15    122
A.B.2   yes     5/25                                
A.B.2                    yes    6/1     119         
A.B.2                                             no    NULL            
A.B.2                                                             no    NULL    NULL
我做错了什么?请帮忙


--K-moj

我猜没有看到您的查询,但是如果您试图用CASE表达式来透视数据,我的建议是围绕CASE添加聚合函数

select
  name,
  max(case when [group] = 'A' then status end) grp_A,
  max(case when [group] = 'A' then date end) A_day,
  max(case when [group] = 'A' then [count] end) A_ct,
  max(case when [group] = 'B' then status end) grp_B,
  max(case when [group] = 'B' then date end) B_day,
  max(case when [group] = 'B' then [count] end) B_ct,
  max(case when [group] = 'C' then status end) grp_C,
  max(case when [group] = 'C' then date end) C_day,
  max(case when [group] = 'C' then [count] end) C_ct,
  max(case when [group] = 'D' then status end) grp_D,
  max(case when [group] = 'D' then date end) D_day,
  max(case when [group] = 'D' then [count] end) D_ct
from yourtable
group by name

如果要使用透视功能,则需要首先查看取消透视
状态
日期
计数
列,然后在最终结果中透视它们

取消PIVOT是指将多列数据转换为多行。您可以使用多种方法取消激活
状态
日期
计数
列。由于您使用的是SQL Server 2012,因此可以将交叉应用与VALUES子句一起使用。将列转换为行的代码如下:

select name, 
  col = col+'_'+[group], 
  value
from yourtable 
cross apply
(
  values 
    ('grp', status),
    ('day', [date]),
    ('ct', cast([count] as varchar(10)))
) c(col, value)
看。这就产生了一个结果:

|  NAME |   COL |  VALUE |
| A.A.1 | grp_A |    yes |
| A.A.1 | day_A |   5/23 |
| A.A.1 |  ct_A | (null) |
| A.A.1 | grp_B |    yes |
| A.A.1 | day_B |   5/27 |
| A.A.1 |  ct_B |    112 |
现在,所有值都将在
value
中转换为新列,而新列名将在
col
中转换,而不是有多个要透视的列。然后,您可以应用PIVOT函数,以便完整代码类似于以下内容:

select name,
  grp_A, day_A, ct_A,
  grp_B, day_B, ct_B,
  grp_C, day_C, ct_C,
  grp_D, day_D, ct_D
from
(
  select name, 
    col = col+'_'+[group], 
    value
  from yourtable 
  cross apply
  (
    values 
      ('grp', status),
      ('day', [date]),
      ('ct', cast([count] as varchar(10)))
  ) c(col, value)
) d
pivot
(
  max(value)
  for col in (grp_A, day_A, ct_A,
              grp_B, day_B, ct_B,
              grp_C, day_C, ct_C,
              grp_D, day_D, ct_D)
) piv

我猜,在没有看到您的查询的情况下查看

,但是如果您试图使用案例表达式来透视数据,我的建议是围绕案例添加聚合函数

select
  name,
  max(case when [group] = 'A' then status end) grp_A,
  max(case when [group] = 'A' then date end) A_day,
  max(case when [group] = 'A' then [count] end) A_ct,
  max(case when [group] = 'B' then status end) grp_B,
  max(case when [group] = 'B' then date end) B_day,
  max(case when [group] = 'B' then [count] end) B_ct,
  max(case when [group] = 'C' then status end) grp_C,
  max(case when [group] = 'C' then date end) C_day,
  max(case when [group] = 'C' then [count] end) C_ct,
  max(case when [group] = 'D' then status end) grp_D,
  max(case when [group] = 'D' then date end) D_day,
  max(case when [group] = 'D' then [count] end) D_ct
from yourtable
group by name

如果要使用透视功能,则需要首先查看取消透视
状态
日期
计数
列,然后在最终结果中透视它们

取消PIVOT是指将多列数据转换为多行。您可以使用多种方法取消激活
状态
日期
计数
列。由于您使用的是SQL Server 2012,因此可以将交叉应用与VALUES子句一起使用。将列转换为行的代码如下:

select name, 
  col = col+'_'+[group], 
  value
from yourtable 
cross apply
(
  values 
    ('grp', status),
    ('day', [date]),
    ('ct', cast([count] as varchar(10)))
) c(col, value)
看。这就产生了一个结果:

|  NAME |   COL |  VALUE |
| A.A.1 | grp_A |    yes |
| A.A.1 | day_A |   5/23 |
| A.A.1 |  ct_A | (null) |
| A.A.1 | grp_B |    yes |
| A.A.1 | day_B |   5/27 |
| A.A.1 |  ct_B |    112 |
现在,所有值都将在
value
中转换为新列,而新列名将在
col
中转换,而不是有多个要透视的列。然后,您可以应用PIVOT函数,以便完整代码类似于以下内容:

select name,
  grp_A, day_A, ct_A,
  grp_B, day_B, ct_B,
  grp_C, day_C, ct_C,
  grp_D, day_D, ct_D
from
(
  select name, 
    col = col+'_'+[group], 
    value
  from yourtable 
  cross apply
  (
    values 
      ('grp', status),
      ('day', [date]),
      ('ct', cast([count] as varchar(10)))
  ) c(col, value)
) d
pivot
(
  max(value)
  for col in (grp_A, day_A, ct_A,
              grp_B, day_B, ct_B,
              grp_C, day_C, ct_C,
              grp_D, day_D, ct_D)
) piv

请参见

我不知道“取消激活”我的字段是什么意思。@user2712237
UNPIVOT
是将多列转换为行的过程,请参见我的编辑我不知道“取消激活”我的字段是什么意思。@user2712237
UNPIVOT
是将多列转换为行的过程,请参见我的编辑