我使用了每日报告的透视查询..
我的表是这样的:
CREATE TABLE IF NOT EXISTS `attendance` (
`empID` int(11) NOT NULL,
`date` date NOT NULL,
`deptID` int(11) NOT NULL,
`attStatus` varchar(3) NOT NULL,
PRIMARY KEY (`empID`,`date`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
对于月度出勤报告,我使用了此查询:
SELECT empID,
GROUP_CONCAT(if(DAY(`date`) = 1, `attStatus`, NULL)) AS 'day1',
GROUP_CONCAT(if(DAY(`date`) = 2, `attStatus`, NULL)) AS 'day2',
GROUP_CONCAT(if(DAY(`date`) = 3, `attStatus`, NULL)) AS 'day3',
GROUP_CONCAT(if(DAY(`date`) = 4, `attStatus`, NULL)) AS 'day4',
GROUP_CONCAT(if(DAY(`date`) = 5, `attStatus`, NULL)) AS 'day5',
GROUP_CONCAT(if(DAY(`date`) = 6, `attStatus`, NULL)) AS 'day6',
GROUP_CONCAT(if(DAY(`date`) = 7, `attStatus`, NULL)) AS 'day7',
GROUP_CONCAT(if(DAY(`date`) = 8, `attStatus`, NULL)) AS 'day8',
GROUP_CONCAT(if(DAY(`date`) = 9, `attStatus`, NULL)) AS 'day9',
GROUP_CONCAT(if(DAY(`date`) = 10, `attStatus`, NULL)) AS 'day10',
GROUP_CONCAT(if(DAY(`date`) = 11, `attStatus`, NULL)) AS 'day11',
GROUP_CONCAT(if(DAY(`date`) = 12, `attStatus`, NULL)) AS 'day12',
GROUP_CONCAT(if(DAY(`date`) = 13, `attStatus`, NULL)) AS 'day13',
GROUP_CONCAT(if(DAY(`date`) = 14, `attStatus`, NULL)) AS 'day14',
GROUP_CONCAT(if(DAY(`date`) = 15, `attStatus`, NULL)) AS 'day15',
GROUP_CONCAT(if(DAY(`date`) = 16, `attStatus`, NULL)) AS 'day16',
GROUP_CONCAT(if(DAY(`date`) = 17, `attStatus`, NULL)) AS 'day17',
GROUP_CONCAT(if(DAY(`date`) = 18, `attStatus`, NULL)) AS 'day18',
GROUP_CONCAT(if(DAY(`date`) = 19, `attStatus`, NULL)) AS 'day19',
GROUP_CONCAT(if(DAY(`date`) = 20, `attStatus`, NULL)) AS 'day20',
GROUP_CONCAT(if(DAY(`date`) = 21, `attStatus`, NULL)) AS 'day21',
GROUP_CONCAT(if(DAY(`date`) = 22, `attStatus`, NULL)) AS 'day22',
GROUP_CONCAT(if(DAY(`date`) = 23, `attStatus`, NULL)) AS 'day23',
GROUP_CONCAT(if(DAY(`date`) = 24, `attStatus`, NULL)) AS 'day24',
GROUP_CONCAT(if(DAY(`date`) = 25, `attStatus`, NULL)) AS 'day25',
GROUP_CONCAT(if(DAY(`date`) = 26, `attStatus`, NULL)) AS 'day26',
GROUP_CONCAT(if(DAY(`date`) = 27, `attStatus`, NULL)) AS 'day27',
GROUP_CONCAT(if(DAY(`date`) = 28, `attStatus`, NULL)) AS 'day28',
GROUP_CONCAT(if(DAY(`date`) = 29, `attStatus`, NULL)) AS 'day29',
GROUP_CONCAT(if(DAY(`date`) = 30, `attStatus`, NULL)) AS 'day30',
GROUP_CONCAT(if(DAY(`date`) = 31, `attStatus`, NULL)) AS 'day31',
COUNT(if(`attStatus`='P', `attStatus`, NULL)) AS 'totalP'
FROM `attendance`
WHERE deptID=1 AND `date` BETWEEN '2011-07-01' AND '2011-07-31'
GROUP BY empID
所以我的问题是,这个查询不是太长了吗? 是否有任何替代此查询来显示月度出勤报告?
如果此查询没问题,那么对于那些有30天的月份,将显示31天的结果。这有什么解决方案吗?
更新
以下是截图,说明了我想要的报告类型:
答案 0 :(得分:0)
不知道你的原始查询是否会起作用,但这样的事情会更简单:
select DAY(date),count(*) from attendance where MONTH(date) = 2 group by DAY(date);
那应该是2月的出席率。输出将是:
+-----------+----------+
| DAY(date) | count(*) |
+-----------+----------+
| 18 | 1 |
| 19 | 2 |
+-----------+----------+
答案 1 :(得分:0)
首先,创建一个帮助表:
CREATE TABLE days
( d TINYINT PRIMARY KEY
) ;
INSERT INTO days
VALUES
(0), (1), (2), ..., (31) ;
然后你可以试试这个。它会返回比查询更少的列:
SELECT
a.empID
, GROUP_CONCAT( CASE WHEN a.attStatus IS NULL
THEN 'N'
ELSE a.attStatus
END
ORDER BY dates.dateCheck)
AS days
, COUNT( CASE WHEN a.attStatus='P' THEN 1 END )
AS totalP
FROM
( SELECT monthStart + INTERVAL d DAY
AS dateCheck
FROM days
CROSS JOIN
( SELECT '2011-07-01' AS monthStart
) AS m
WHERE MONTH(monthStart + INTERVAL d DAY) = MONTH(monthStart)
) AS dates
LEFT JOIN attendance AS a
ON a.`date` = dates.dateCheck
WHERE a.deptID = 1
GROUP BY a.empID