我正在尝试在3个字段/列上使用PIVOT,即站点,值,日期。我正在使用SQLServer 2008.请检查下面我的实际表和所需的输出表以及我使用的数据透视查询
实际表格:
**tblReference**
**ID** **Refer_code** **Site** **Value** **Date**
1 9290 CA 12.5 2014-01-01 20:20:41
5 9290 TX 12.6 2014-01-05 18:20:30
2 6651 CA 13.5 2014-01-01 21:20:21
3 7442 TX 14.5 2014-01-05 19:15:14
4 8093 CA 15.5 2014-01-01 19:20:20
6 8093 TX 16.5 2014-01-05 20:20:20
**Desired output table:**
**Refer_code** **Site_1** **Site_2** **Val_1** **Val_2** **StartDate** **EndDate**
9290 CA TX 12.5 12.6 2014-01-01 2014-01-05
20:20:41 18:20:30
6651 CA NULL 13.5 NULL 2014-01-01 NULL
21:20:21
7442 NULL TX NULL 14.5 NULL 2014-01-05
19:15:14
8093 CA TX 15.5 16.5 2014-01-01 2014-01-05
19:20:20 20:20:20
**Query:**
SELECT Refer_code, [Site_1], [Site_2], [Date_1] AS StartDate, [Date_2] AS EndDate, [Val_1], [Val_2]
FROM
(
SELECT Refer_code, Site, 'Site_'+ cast(row_number() over(partition by Refer_code order by Date) as nvarchar(50)) SiteVal,Date,'Date_'+cast(row_number() over(partition by Refer_code order by Date) as nvarchar(50)) DateVal,Value,'Val_'+cast(row_number() over(partition by Refer_code order by Date) as nvarchar(50)) Val
FROM tblReference
) x
pivot
(
min(Site)
for SiteVal in ([Site_1], [Site_2])
) p
pivot
(
min(Date)
for DateVal in ([Date_1], [Date_2])
) s
pivot
(
min(Value)
for Val in ([Val_1], [Val_2])
) t
上述查询未按预期返回结果。请帮我解决。
答案 0 :(得分:2)
有几种方法可以获得所需的结果。最简单的方法可能是使用带有CASE表达式的聚合函数,但您也可以使用PIVOT函数。
与CASE聚合:
我会采取以下步骤,首先使用refer_code
为每个row_number()
创建一个唯一的序列:
select refer_code, site,
row_number() over(partition by refer_code
order by date) seq,
value,
date
from tblReference;
拥有唯一序列后,您可以通过应用带有CASE表达式的聚合函数轻松将现有数据转换为多个列:
;with cte as
(
select refer_code, site,
row_number() over(partition by refer_code
order by date) seq,
value,
date
from tblReference
)
select refer_code,
max(case when seq = 1 then site end) site1,
max(case when seq = 2 then site end) site2,
max(case when seq = 1 then value end) value1,
max(case when seq = 2 then value end) value2,
max(case when seq = 1 then date end) startdate,
max(case when seq = 2 then date end) enddate
from cte
group by refer_code;
<强> PIVOT:强>
如果你想使用PIVOT功能,你需要转动多个列,我建议先看看这些列的转换,然后应用pivot功能。您需要创建用于新列名称的唯一序列,然后您需要取消忽略site
,date
和value
列。由于您使用的是SQL Server 2008+,因此可以CROSS APPLY
使用VALUEs
将多列拆分为多行:
;with cte as
(
select refer_code, site,
row_number() over(partition by refer_code
order by date) seq,
value,
date
from tblReference
)
select *
from
(
select refer_code,
col = col + cast(seq as varchar(10)),
val
from cte
cross apply
(
values
('Site', site),
('Value', cast(value as varchar(10))),
('Date', convert(varchar(10), date, 120))
) c (col, val)
) d;
见SQL Fiddle with Demo。这会使您的数据格式为:
| REFER_CODE | COL | VAL |
|------------|--------|------------|
| 6651 | Site1 | CA |
| 6651 | Value1 | 13.50 |
| 6651 | Date1 | 2014-01-01 |
| 7442 | Site1 | TX |
| 7442 | Value1 | 14.50 |
| 7442 | Date1 | 2014-01-05 |
现在您可以轻松应用pivot函数来获得最终结果,因此整个代码将是:
;with cte as
(
select refer_code, site,
row_number() over(partition by refer_code
order by date) seq,
value,
date
from tblReference
)
select refer_code,
site1, site2,
startdate = date1, enddate = date2,
value1, value2
from
(
select refer_code,
col = col + cast(seq as varchar(10)),
val
from cte
cross apply
(
values
('Site', site),
('Value', cast(value as varchar(10))),
('Date', convert(varchar(10), date, 120))
) c (col, val)
) d
pivot
(
max(val)
for col in (site1, site2, date1, date2,
value1, value2)
) piv;
见SQL Fiddle with Demo。两者都会给出结果:
| REFER_CODE | SITE1 | SITE2 | STARTDATE | ENDDATE | VALUE1 | VALUE2 |
|------------|-------|--------|------------|------------|--------|--------|
| 6651 | CA | (null) | 2014-01-01 | (null) | 13.50 | (null) |
| 7442 | TX | (null) | 2014-01-05 | (null) | 14.50 | (null) |
| 8093 | CA | TX | 2014-01-01 | 2014-01-05 | 15.50 | 16.50 |
| 9290 | CA | TX | 2014-01-01 | 2014-01-05 | 12.50 | 12.60 |
编辑:
根据您的评论,您需要将列CA
设置为site1
等,然后获得结果的最简单方法是使用带CASe的聚合函数:
select refer_code,
max(case when site = 'CA' then site end) site1,
max(case when site = 'TX' then site end) site2,
max(case when site = 'CA' then value end) value1,
max(case when site = 'TX' then value end) value2,
max(case when site = 'CA' then date end) startdate,
max(case when site = 'TX' then date end) endate
from tblReference
group by refer_code;
见SQL Fiddle with Demo。这给出了一个结果:
| REFER_CODE | SITE1 | SITE2 | VALUE1 | VALUE2 | STARTDATE | ENDATE |
|------------|--------|--------|--------|--------|--------------------------------|--------------------------------|
| 6651 | CA | (null) | 13.5 | (null) | January, 01 2014 21:20:21+0000 | (null) |
| 7442 | (null) | TX | (null) | 14.5 | (null) | January, 05 2014 19:15:14+0000 |
| 8093 | CA | TX | 15.5 | 16.5 | January, 01 2014 19:20:20+0000 | January, 05 2014 20:20:20+0000 |
| 9290 | CA | TX | 12.5 | 12.6 | January, 01 2014 20:20:41+0000 | January, 05 2014 18:20:30+0000 |