[英]SQL - Grouping with aggregation
I have a table (TABLE1) that lists all employees with their Dept IDs, the date they started and the date they were terminated (NULL means they are current employees). 我有一个表(TABLE1),其中列出了所有雇员及其部门ID,开始日期和终止日期(NULL表示他们是当前雇员)。
I would like to have a resultset (TABLE2) , in which every row represents a day starting since the first employee started( in the sample table below, that date is 20090101 ), till today. 我想要一个结果集(TABLE2),其中每一行都代表自第一位员工开始以来的一天(在下面的示例表中,该日期是20090101),直到今天。 (the DATE field).
(DATE字段)。 I would like to group the employees by DeptID and calculate the total number of employees for each row of TABLE2.
我想按DeptID对员工进行分组,并为TABLE2的每一行计算员工总数。
How do I this query? 我如何查询? Thanks for your help, in advance.
预先感谢您的帮助。
TABLE1 表格1
DeptID EmployeeID StartDate EndDate
--------------------------------------------
001 123 20100101 20120101
001 124 20090101 NULL
001 234 20110101 20120101
TABLE2 TABLE2
DeptID Date EmployeeCount
-----------------------------------
001 20090101 1
001 20090102 1
... ... 1
001 20100101 2
001 20100102 2
... ... 2
001 20110101 3
001 20110102 3
... ... 3
001 20120101 1
001 20120102 1
001 20120103 1
... ... 1
This will work if you have a date
look up table. 如果您有
date
查询表,这将起作用。 You will need to specify the department ID. 您将需要指定部门ID。 See it in action .
看到它在行动 。
Query 询问
SELECT d.dt, SUM(e.ecount) AS RunningTotal
FROM dates d
INNER JOIN
(SELECT b.dt,
CASE
WHEN c.ecount IS NULL THEN 0
ELSE c.ecount
END AS ecount
FROM dates b
LEFT JOIN
(SELECT a.DeptID, a.dt, SUM([count]) AS ecount
FROM
(SELECT DeptID, EmployeeID, 1 AS [count], StartDate AS dt FROM TABLE1
UNION ALL
SELECT DeptID, EmployeeID,
CASE
WHEN EndDate IS NOT NULL THEN -1
ELSE 0
END AS [count], EndDate AS dt FROM TABLE1) a
WHERE a.dt IS NOT NULL AND DeptID = 1
GROUP BY a.DeptID, a.dt) c ON c.dt = b.dt) e ON e.dt <= d.dt
GROUP BY d.dt
Result 结果
| DT | RUNNINGTOTAL | ----------------------------- | 2009-01-01 | 1 | | 2009-02-01 | 1 | | 2009-03-01 | 1 | | 2009-04-01 | 1 | | 2009-05-01 | 1 | | 2009-06-01 | 1 | | 2009-07-01 | 1 | | 2009-08-01 | 1 | | 2009-09-01 | 1 | | 2009-10-01 | 1 | | 2009-11-01 | 1 | | 2009-12-01 | 1 | | 2010-01-01 | 2 | | 2010-02-01 | 2 | | 2010-03-01 | 2 | | 2010-04-01 | 2 | | 2010-05-01 | 2 | | 2010-06-01 | 2 | | 2010-07-01 | 2 | | 2010-08-01 | 2 | | 2010-09-01 | 2 | | 2010-10-01 | 2 | | 2010-11-01 | 2 | | 2010-12-01 | 2 | | 2011-01-01 | 3 | | 2011-02-01 | 3 | | 2011-03-01 | 3 | | 2011-04-01 | 3 | | 2011-05-01 | 3 | | 2011-06-01 | 3 | | 2011-07-01 | 3 | | 2011-08-01 | 3 | | 2011-09-01 | 3 | | 2011-10-01 | 3 | | 2011-11-01 | 3 | | 2011-12-01 | 3 | | 2012-01-01 | 1 |
Schema 架构
CREATE TABLE TABLE1 (
DeptID tinyint,
EmployeeID tinyint,
StartDate date,
EndDate date)
INSERT INTO TABLE1 VALUES
(1, 123, '2010-01-01', '2012-01-01'),
(1, 124, '2009-01-01', NULL),
(1, 234, '2011-01-01', '2012-01-01')
CREATE TABLE dates (
dt date)
INSERT INTO dates VALUES
('2009-01-01'), ('2009-02-01'), ('2009-03-01'), ('2009-04-01'), ('2009-05-01'),
('2009-06-01'), ('2009-07-01'), ('2009-08-01'), ('2009-09-01'), ('2009-10-01'),
('2009-11-01'), ('2009-12-01'), ('2010-01-01'), ('2010-02-01'), ('2010-03-01'),
('2010-04-01'), ('2010-05-01'), ('2010-06-01'), ('2010-07-01'), ('2010-08-01'),
('2010-09-01'), ('2010-10-01'), ('2010-11-01'), ('2010-12-01'), ('2011-01-01'),
('2011-02-01'), ('2011-03-01'), ('2011-04-01'), ('2011-05-01'), ('2011-06-01'),
('2011-07-01'), ('2011-08-01'), ('2011-09-01'), ('2011-10-01'), ('2011-11-01'),
('2011-12-01'), ('2012-01-01')
you need somthing along these lines. 您需要遵循以下原则。
SELECT *
, ( SELECT COUNT(EmployeeID) AS EmployeeCount
FROM TABLE1 AS f
WHERE t.[Date] BETWEEN f.BeginDate AND f.EndDate
)
FROM ( SELECT DeptID
, BeginDate AS [Date]
FROM TABLE1
UNION
SELECT DeptID
, EndDate AS [Date]
FROM TABLE1
) AS t
EDIT since OP clarified that he wants all the dates here is the updated solution I have excluded a Emplyee from Count if his job is ending on that date.But if you want to include change t.[Date] < f.EndDate
to t.[Date] <= f.EndDate
in the below solution. 自OP以来的编辑澄清说,他希望这里的所有日期都是更新的解决方案,如果他的工作在该日期结束,则我从Count中排除了Emplyee。但是,如果要包括更改
t.[Date] < f.EndDate
到t.[Date] <= f.EndDate
在以下解决方案中。 Plus I assume the NULL
value in EndDate mean Employee still works for Department. 另外,我假设EndDate中的
NULL
值表示Employee仍在Department上工作。
DECLARE @StartDate DATE = (SELECT MIN(StartDate) FROM Table1)
,@EndDate DATE = (SELECT MAX(EndDate) FROM Table1)
;WITH CTE AS
(
SELECT DISTINCT DeptID,@StartDate AS [Date] FROM Table1
UNION ALL
SELECT c.DeptID, DATEADD(dd,1,c.[Date]) AS [Date] FROM CTE AS c
WHERE c.[Date]<=@EndDate
)
SELECT * ,
EmployeeCount=( SELECT COUNT(EmployeeID)
FROM TABLE1 AS f
WHERE f.DeptID=t.DeptID AND t.[Date] >= f.StartDate
AND ( t.[Date] < f.EndDate OR f.EndDate IS NULL )
)
FROM CTE AS t
ORDER BY 1
OPTION ( MAXRECURSION 0 )
here is SQL Fiddler demo.I have added another department and added an Employee to it. 这是SQL Fiddler演示。我添加了另一个部门并为其添加了一个Employee。
http://sqlfiddle.com/#!3/5c4ec/1 http://sqlfiddle.com/#!3/5c4ec/1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.