简体   繁体   English

SQL-聚合分组

[英]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.EndDatet.[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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM