/*创建表,插入测试数据*/
CREATE TABLE Tbl_Test(工号 varchar(10),日期 datetime)
INSERT INTO Tbl_Test
SELECT '00000523','2007-10-12 17:31:49' UNION ALL
SELECT '00000523','2007-10-12 13:52:32' UNION ALL
SELECT '00000523','2007-10-12 12:12:32' UNION ALL
SELECT '00000523','2007-10-12 07:52:32'
/*方法一、静态SQL转置(用于列数已知)
基本思路:
1、最内层Sql(T2内),先计算出最终会有几列
2、把数据查询成为工号、日期、时间、时间列号 格式
3、转置
*/
SELECT 工号,TDate,
'日期1'=MAX(CASE 日期序列 WHEN '日期1' THEN TTime ELSE '' END),
'日期2'=MAX(CASE 日期序列 WHEN '日期2' THEN TTime ELSE '' END),
'日期3'=MAX(CASE 日期序列 WHEN '日期3' THEN TTime ELSE '' END),
'日期4'=MAX(CASE 日期序列 WHEN '日期4' THEN TTime ELSE '' END)
FROM
(SELECT 工号,Convert(varchar(10),日期,121) as TDate,Convert(varchar(8),日期,108) as TTime,'日期'+CAST(MAX(TimeOrder) as varchar) as 日期序列 FROM
(SELECT *,'TimeOrder'=(SELECT COUNT(1)+1 FROM Tbl_Test WHERE 工号= T1.工号 and 日期 < T1.日期) FROM Tbl_Test T1) T2
GROUP BY 工号,Convert(varchar(10),日期,121),Convert(varchar(8),日期,108)) T3
GROUP BY 工号,TDate
/*方法二,动态SQL转置(用于列数未知)
动态转置一般都要用到中间表,此处生成了一个中间表Tbl_Test2,当然也可以不用,把sql改一下即可,sql会有点长
基本思路:
1、最内层Sql(T2内),先计算出最终会有几列
2、把数据查询成为工号、日期、时间、时间列号 格式,生成中间表
3、根据分组动态生成最终查询用的sql
4、执行sql
*/
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[Tbl_Test2]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) drop table [dbo].[Tbl_Test2]
SELECT 工号,Convert(varchar(10),日期,121) as TDate,Convert(varchar(8),日期,108) as TTime,'日期'+CAST(MAX(TimeOrder) as varchar) as 日期序列 INTO Tbl_Test2 FROM
(SELECT *,'TimeOrder'=(SELECT COUNT(1)+1 FROM Tbl_Test WHERE 工号= T1.工号 and 日期 < T1.日期) FROM Tbl_Test T1) T2
GROUP BY 工号,Convert(varchar(10),日期,121),Convert(varchar(8),日期,108)
GO
DECLARE @s varchar(8000)
SELECT @s = ''
SELECT @s = @s + ',MAX(CASE 日期序列 WHEN '''+日期序列+''' THEN TTime ELSE '''' END) as '+日期序列 FROM Tbl_Test2 GROUP BY 工号,TDate,日期序列
Exec('SELECT 工号,TDate' + @s + ' FROM Tbl_Test2 GROUP BY 工号,TDate')
/*删除测试用表*/
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[Tbl_Test2]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) drop table [dbo].[Tbl_Test2]
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[Tbl_Test]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) drop table [dbo].[Tbl_Test]