sqlserver 按一天时间段行转列 ([上午上班时间] [上午下班时间] [下午上班时间] [下午下班时间] )

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sqlserver 按一天时间段行转列 ([上午上班时间] [上午下班时间] [下午上班时间] [下午下班时间] )相关的知识,希望对你有一定的参考价值。

一张表内,储存了员工打卡的全部记录

如2011年8月1号
*************************************************
[员工EmployeeID] [打卡时间CardTime ]
1 2011-08-01 08:01:27
1 2011-08-01 11:33:27

1 2011-08-01 13:32:27
1 2011-08-01 17:30:27

2 2011-08-01 08:22:27
2 2011-08-01 11:21:27
2 2011-08-01 17:32:27
*************************************************

现在要实现的功能
查询每个员工打卡一天4条记录(也可能少于4条记录,因为没打卡) 转成1行4列怎么写

查询后如下:
*************************************************
[员工ID] [上午上班时间] [上午下班时间] [下午上班时间] [下午下班时间]

1 8:01 11:33 13:32 17:30
2 8:22 11:21 17:32
*************************************************

其中上下班时间段为
( convert(varchar(10), c.CardTime ,8) between '07:00:00' and '10:00:00')
上午下班时间段
( convert(varchar(10), c.CardTime ,8) between '11:00:00' and '13:00:00')
下午上班时间段
( convert(varchar(10), c.CardTime ,8) between '13:00:00' and '15:00:00')
下午下班时间段
( convert(varchar(10), c.CardTime ,8) between '17:00:00' and '00:00:00')

CREATE TABLE #test(
EmployeeID INT,
CardTime DATETIME
);
go

INSERT INTO #test
SELECT 1, '2011-08-01 08:01:27' UNION ALL
SELECT 1, '2011-08-01 11:33:27' UNION ALL
SELECT 1, '2011-08-01 13:32:27' UNION ALL
SELECT 1, '2011-08-01 17:30:27' UNION ALL
SELECT 2, '2011-08-01 08:22:27' UNION ALL
SELECT 2, '2011-08-01 11:21:27' UNION ALL
SELECT 2, '2011-08-01 17:32:27'
go

with myCTE AS (
SELECT
c.EmployeeID,
c.CardTime,
CASE
WHEN (convert(varchar(10), c.CardTime ,8) between '07:00:00' and '10:00:00')
THEN '上午上班时间'
WHEN ( convert(varchar(10), c.CardTime ,8) between '11:00:00' and '13:00:00')
THEN '上午下班时间'
WHEN ( convert(varchar(10), c.CardTime ,8) between '13:00:00' and '15:00:00')
THEN '下午上班时间 '
ELSE
'下午下班时间'
END as TimePart
FROM
#test c
)
SELECT
*
FROM
myCTE
PIVOT(
MIN(CardTime)
FOR TimePart IN ([上午上班时间], [上午下班时间], [下午上班时间], [下午下班时间] )
) tmp

EmployeeID 上午上班时间 上午下班时间 下午上班时间 下午下班时间
----------- ----------------------- ----------------------- ----------------------- -----------------------
1 2011-08-01 08:01:27.000 2011-08-01 11:33:27.000 2011-08-01 13:32:27.000 2011-08-01 17:30:27.000
2 2011-08-01 08:22:27.000 2011-08-01 11:21:27.000 NULL 2011-08-01 17:32:27.000

(2 行受影响)追问

高手你好

如果不止一天呢...一个员工有多天上班
除了4个时间段外,把日期也列出一列来呢

应该如何写啊...
谢谢

追答

with myCTE AS (
SELECT
c.EmployeeID,
CONVERT(varchar(10), c.CardTime, 120) AS CardDate,
c.CardTime,
CASE
WHEN (convert(varchar(10), c.CardTime ,8) between '07:00:00' and '10:00:00')
THEN '上午上班时间'
WHEN ( convert(varchar(10), c.CardTime ,8) between '11:00:00' and '13:00:00')
THEN '上午下班时间'
WHEN ( convert(varchar(10), c.CardTime ,8) between '13:00:00' and '15:00:00')
THEN '下午上班时间 '
ELSE
'下午下班时间'
END as TimePart
FROM
#test c
)
SELECT
*
FROM
myCTE
PIVOT(
MIN(CardTime)
FOR TimePart IN ([上午上班时间], [上午下班时间], [下午上班时间], [下午下班时间] )
) tmp

追问

如果再加4一个标识
如果存在这种情况,用1标识,如果不是用0标识
迟到时间:8:35---10:00 14:05---15:00
早退时间:11:00—12:00 17:00---17:30

[员工ID] [上午上班时间] [上午下班时间] [下午上班时间] [下午下班时间] [上午迟到][上午早退][下午迟到][下午早退]

追答

没打卡的, 怎么算迟到早退?

SQL 太长, 已经出现:
您修改后的回答正在自动提交中,请您耐心等候几分钟。非常感谢您补充完善回答!

with myCTE AS (
SELECT
c.EmployeeID,
CONVERT(varchar(10), c.CardTime, 120) AS CardDate,
c.CardTime,
CASE
WHEN (convert(varchar(10), c.CardTime ,8) between '07:00:00' and '10:00:00')
THEN '上午上班时间'
WHEN ( convert(varchar(10), c.CardTime ,8) between '11:00:00' and '13:00:00')
THEN '上午下班时间'
WHEN ( convert(varchar(10), c.CardTime ,8) between '13:00:00' and '15:00:00')
THEN '下午上班时间 '
ELSE
'下午下班时间'
END as TimePart
FROM
#test c
),
baseCTE AS (
SELECT
EmployeeID,
CardDate,
MAX( CASE WHEN TimePart='上午上班时间' THEN CardTime ELSE NULL END ) AS [上午上班时间],
MIN( CASE WHEN TimePart='上午下班时间' THEN CardTime ELSE NULL END ) AS [上午下班时间],
MAX( CASE WHEN TimePart='下午上班时间' THEN CardTime ELSE NULL END ) AS [下午上班时间],
MIN( CASE WHEN TimePart='下午下班时间' THEN CardTime ELSE NULL END ) AS [下午下班时间]
FROM
myCTE
GROUP BY
EmployeeID,
CardDate
)
SELECT
EmployeeID,
CardDate,
[上午上班时间],
[上午下班时间],
[下午上班时间],
[下午下班时间],
CASE
WHEN (convert(varchar(10), [上午上班时间] ,8) between '08:35:00' and '10:00:00')
THEN 1
ELSE 0
END AS [上午迟到],
CASE
WHEN (convert(varchar(10), [上午下班时间] ,8) between '10:00:00' and '12:00:00')
THEN 1
ELSE 0
END AS
[上午早退],
CASE
WHEN (convert(varchar(10), [下午上班时间] ,8) between '14:05:00' and '15:00:00')
THEN 1
ELSE 0
END AS
[下午迟到],
CASE
WHEN (convert(varchar(10), [下午下班时间] ,8) between '17:00:00' and '17:30:00')
THEN 1
ELSE 0
END AS [下午早退]
FROM
baseCTE;

参考技术A 那你只有把基本表里的字段改成 每个你要显示的属性

如 [员工ID] [上午上班时间] [上午下班时间] [下午上班时间] [下午下班时间]
那么查询出来就是这样的了
参考技术B select id col1 as bb from tb
union all
select id col2 as bb from tb
......
参考技术C

以上是关于sqlserver 按一天时间段行转列 ([上午上班时间] [上午下班时间] [下午上班时间] [下午下班时间] )的主要内容,如果未能解决你的问题,请参考以下文章

sqlserver怎么行转列?

sqlserver 行转列(转)

SQLServer pivot 行转列

Sqlserver 列转行 行转列

SqlServer基本操作

死磕:SQL行转列汇总(全网最全最详细)