我正在使用SQL Server Management Studio 2012,并希望为超过2300行的表创建数据透视/交叉制表符查询。
该表有5列:
- name
- group
- status
- date
- count
大约有580个不同的名字。
每个名称与4个不同的组(A,B,C和D)相关联。
每个小组的完整状态为是或否。
完成后,日期与每个状态相关联。否则,状态为NULL。
count列仅适用于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个库存中间隔开。
样本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
答案 0 :(得分:1)
我没有看到您的查询,但是如果您尝试使用CASE表达式对数据进行PIVOT,我的建议是在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功能,你需要首先看看status
,date
和count
列的隐蔽,然后在最终结果中转动它们。
UNPIVOT是将多列数据转换为多行的时候。您可以使用各种方法取消忽略status
,date
和count
列。由于您使用的是SQL Server 2012,因此可以将CROSS APPLY与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)
见Demo。这给出了一个结果:
| 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