【发布时间】:2014-02-04 14:36:05
【问题描述】:
我有一个考勤表和一个包含活动类型的表
我想将每个人每月的活动分组到不同的列中
示例表:
出席
个人 ID
日期
门入
门出
活动ID
活动
身份证
名称
值是 Activity。名称是:Present、Absence、Ill 和 Holiday
我想获得类似的视图(按个人 ID 和月份分组
个人ID
月
年份
缺席
假期
生病
少于 4 小时
超过 4 小时
超过 5 小时
创建此分组的最佳方法是什么? 我已经有两条 SQL 语句,但似乎都太不友好了
谁能帮帮我??? 谢谢
SELECT year(att.Date) as cYear, month(att.Date) as cMonth, att.PersonID, COUNT(1) as Absence, 0 as Holiday, 0 as Ill, 0 as LessThan4Hours, 0 as MoreThan4Hours, 0 as MoreThan5Hours
FROM Attendance att
inner join Activities act on att.ActivityID = act.ID
WHERE act.Name = 'Absence'
GROUP BY year(att.Date), month(att.Date), att.PersonID
UNION
SELECT year(att.Date) as cYear, month(att.Date) as cMonth, att.PersonID, 0 as Absence, COUNT(1) as Holiday, 0 as Ill, 0 as LessThan4Hours, 0 as MoreThan4Hours, 0 as MoreThan5Hours
FROM Attendance att
inner join Activities act on att.ActivityID = act.ID
WHERE act.Name = 'Holiday'
GROUP BY year(att.Date), month(att.Date), att.PersonID
UNION
SELECT year(att.Date) as cYear, month(att.Date) as cMonth, att.PersonID, 0 as Absence, 0 as Holiday, count(1) as Ill, 0 as LessThan4Hours, 0 as MoreThan4Hours, 0 as MoreThan5Hours
FROM Attendance att
inner join Activities act on att.ActivityID = act.ID
WHERE act.Name = 'Ill'
GROUP BY year(att.Date), month(att.Date), att.PersonID
UNION
SELECT year(att.Date) as cYear, month(att.Date) as cMonth, att.PersonID, 0 as Absence, 0 as Holiday, 0 as Ill, COUNT(1) as LessThan4Hours, 0 as MoreThan4Hours, 0 as MoreThan5Hours
FROM Attendance att
inner join Activities act on att.ActivityID = act.ID
WHERE att.GateOut is not null
AND (DATEDIFF(n, att.GateIn, att.GateOut)/60) <= 4
AND act.Name = 'Present'
GROUP BY year(att.Date), month(att.Date), att.PersonID
UNION
SELECT year(att.Date) as cYear, month(att.Date) as cMonth, att.PersonID, 0 as Absence, 0 as Holiday, 0 as Ill, 0 as LessThan4Hours, COUNT(1) as MoreThan4Hours, 0 as MoreThan5Hours
FROM Attendance att
inner join Activities act on att.ActivityID = act.ID
WHERE att.GateOut is not null
AND (DATEDIFF(n, att.GateIn, att.GateOut)/60) > 4
AND (DATEDIFF(n, att.GateIn, att.GateOut)/60) <= 5
AND act.Name = 'Present'
GROUP BY year(att.Date), month(att.Date), att.PersonID
UNION
SELECT year(att.Date) as cYear, month(att.Date) as cMonth, att.PersonID, 0 as Absence, 0 as Holiday, 0 as Ill, 0 as LessThan4Hours, 0 as MoreThan4Hours, COUNT(1) as MoreThan5Hours
FROM Attendance att
inner join Activities act on att.ActivityID = act.ID
WHERE att.GateOut is not null
AND (DATEDIFF(n, att.GateIn, att.GateOut)/60) > 5
AND act.Name = 'Present'
GROUP BY year(att.Date), month(att.Date), att.PersonID
我也在 SELECT CASE 中解决了这个问题,可能更糟?
SELECT a.PersonID, a.cYear, a.cMonth, SUM(a.Absence) AS Absence, SUM(a.Holiday) AS Holiday, SUM(a.Ill) AS Ill, SUM(a.LessThan4Hours) AS LessThan4Hours, SUM(a.MoreThan4Hours) AS MoreThan4Hours, SUM(a.MoreThan5Hours) AS MoreThan5Hours
FROM
(
SELECT year(att.Date) as cYear, month(att.Date) as cMonth, att.PersonID, CASE
WHEN act.Name = 'Ill' THEN 1
WHEN act.Name = 'Holiday' THEN 0
WHEN act.Name = 'Absence' THEN 0
WHEN GateOut = null THEN 0
WHEN (DATEDIFF(n, gatein, gateout)/60) > 5 THEN 0
WHEN (DATEDIFF(n, gatein, gateout)/60) > 4 THEN 0
WHEN (DATEDIFF(n, gatein, gateout)/60) <= 4 THEN 0
ELSE 0
END AS Ill,
CASE
WHEN act.Name = 'Ill' THEN 0
WHEN act.Name = 'Holiday' THEN 1
WHEN act.Name = 'Absence' THEN 0
WHEN GateOut = null THEN 0
WHEN (DATEDIFF(n, gatein, gateout)/60) > 5 THEN 0
WHEN (DATEDIFF(n, gatein, gateout)/60) > 4 THEN 0
WHEN (DATEDIFF(n, gatein, gateout)/60) <= 4 THEN 0
ELSE 0
END AS Holiday,
CASE
WHEN act.Name = 'Ill' THEN 0
WHEN act.Name = 'Holiday' THEN 0
WHEN act.Name = 'Absence' THEN 1
WHEN GateOut = null THEN 0
WHEN (DATEDIFF(n, gatein, gateout)/60) > 5 THEN 0
WHEN (DATEDIFF(n, gatein, gateout)/60) > 4 THEN 0
WHEN (DATEDIFF(n, gatein, gateout)/60) <= 4 THEN 0
ELSE 0
END AS Absence,
CASE
WHEN act.Name = 'Ill' THEN 0
WHEN act.Name = 'Holiday' THEN 0
WHEN act.Name = 'Absence' THEN 0
WHEN GateOut = null THEN 0
WHEN (DATEDIFF(n, gatein, gateout)/60) > 5 THEN 1
WHEN (DATEDIFF(n, gatein, gateout)/60) > 4 THEN 0
WHEN (DATEDIFF(n, gatein, gateout)/60) <= 4 THEN 0
ELSE 0
END AS MoreThan5Hours,
CASE
WHEN act.Name = 'Ill' THEN 0
WHEN act.Name = 'Holiday' THEN 0
WHEN act.Name = 'Absence' THEN 0
WHEN GateOut = null THEN 0
WHEN (DATEDIFF(n, gatein, gateout)/60) > 5 THEN 0
WHEN (DATEDIFF(n, gatein, gateout)/60) > 4 THEN 1
WHEN (DATEDIFF(n, gatein, gateout)/60) <= 4 THEN 0
ELSE 0
END AS MoreThan4Hours,
CASE
WHEN act.Name = 'Ill' THEN 0
WHEN act.Name = 'Holiday' THEN 0
WHEN act.Name = 'Absence' THEN 0
WHEN GateOut = null THEN 0
WHEN (DATEDIFF(n, gatein, gateout)/60) > 5 THEN 0
WHEN (DATEDIFF(n, gatein, gateout)/60) > 4 THEN 0
WHEN (DATEDIFF(n, gatein, gateout)/60) <= 4 THEN 1
ELSE 0
END AS LessThan4Hours
from Attendance att
inner join Activities act on att.ActivityID = act.ID
) a
GROUP BY a.PersonID, a.cYear, a.cMonth
ORDER BY a.cYear DESC, a.cMonth DESC, a.PersonID
【问题讨论】: