转置表

时间:2012-10-17 03:59:11

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

我到处寻找并没有找到任何有用的东西。

我有一张桌子,为员工提供捕获帮助。

看起来像这样的表:

ID   | DATE     | ATTENDANCE
________________
2524 | 20121001 | ASISTANCE
2525 | 20121001 | ABSCENCE
2526 | 20121001 | ASISTANCE
2527 | 20121001 | ASISTANCE
2524 | 20121002 | ASISTANCE
2525 | 20121002 | ABSCENCE
2526 | 20121002 | ASISTANCE
2527 | 20121002 | ASISTANCE
2524 | 20121003 | ASISTANCE
2525 | 20121003 | DAY OFF
2526 | 20121003 | DAY OFF
2527 | 20121003 | ASISTANCE

我想要一个返回表格的查询:

ID   | 20121001  | 20121002  | 20121003
________________
2524 | ASISTANCE | ASISTANCE | ASISTANCE
2525 | ABSCENCE  | ABSCENCE  | DAY OFF
2526 | ASISTANCE | ASISTANCE | ASISTANCE
2527 | ASISTANCE | ASISTANCE | DAY OFF

我尝试过单独的查询并加入它们,但由于它们涉及很多日期,所以需要花费太多时间。

我怎样才能做到有效并且可以存储到视图或函数中?

2 个答案:

答案 0 :(得分:1)

获取数据并使用PHP等服务器端语言处理它会更容易。那么构建数组将是一件小事:

$entry[$id][$date] = $status;

然后:

echo "ID";
foreach(array_keys(array_values($entry)[0]) as $date) {
    // requires some temporary variables in PHP before 5.4
    echo "\t".$date;
}
foreach($entry as $id=>$days) {
    echo "\n".$id;
    foreach($days as $day) echo "\t".$day;
}

您现在有一个以制表符分隔的表格。

答案 1 :(得分:0)

实际上,可以使用PIVOT功能完成此操作。有两种方法可以使用PIVOT,无论是静态还是动态。

Static Pivot,您将硬编码值以变成列:

create table tablea
(
    id int,
    dt datetime,
    attendance varchar(20)
);

insert into tablea values
(2524 , '20121001' , 'ASISTANCE'),
(2525 , '20121001' , 'ABSCENCE'),
(2526 , '20121001' , 'ASISTANCE'),
(2527 , '20121001' , 'ASISTANCE'),
(2524 , '20121002' , 'ASISTANCE'),
(2525 , '20121002' , 'ABSCENCE'),
(2526 , '20121002' , 'ASISTANCE'),
(2527 , '20121002' , 'ASISTANCE'),
(2524 , '20121003' , 'ASISTANCE'),
(2525 , '20121003' , 'DAY OFF'),
(2526 , '20121003' , 'DAY OFF'),
(2527 , '20121003' , 'ASISTANCE');

select *
from
(
    select id, dt, attendance
    from tablea
) x
pivot
(
    max(attendance)
    for dt in ([2012-10-01], [2012-10-02], [2012-10-03])
) p;

动态PIVOT将在运行时获取值列表,并且如果列表发生更改,则会更灵活:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(convert(char(10), dt, 120)) 
                    from tablea
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT id, ' + @cols + ' from 
             (
                select id, dt, attendance
                from tablea
            ) x
            pivot 
            (
                max(attendance)
                for dt in (' + @cols + ')
            ) p '

execute(@query)

两者都会给出相同的结果:

id   | 2012-10-01 | 2012-10-02 | 2012-10-03
-------------------------------------------
2524 | ASISTANCE  | ASISTANCE  | ASISTANCE
2525 | ABSCENCE   | ABSCENCE   | DAY OFF
2526 | ASISTANCE  | ASISTANCE  | DAY OFF
2527 | ASISTANCE  | ASISTANCE  | ASISTANCE