0

すべての従業員とその部門ID、開始日、終了日を一覧表示するテーブル(TABLE1)があります(NULLは現在の従業員であることを意味します)。

結果セット(表2)が必要です。ここで、すべての行は、最初の従業員が開始してから今日までの日を表します(以下のサンプル表では、その日付は20090101です)。(DATEフィールド)。従業員をDeptIDでグループ化し、TABLE2の各行の従業員の総数を計算したいと思います。

このクエリを実行するにはどうすればよいですか?よろしくお願いします。

表1

DeptID     EmployeeID   StartDate   EndDate
--------------------------------------------
001        123           20100101   20120101   
001        124           20090101   NULL
001        234           20110101   20120101

表2

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
4

2 に答える 2

3

dateこれは、ルックアップテーブルがある場合に機能します。部門IDを指定する必要があります。実際の動作をご覧ください。

クエリ

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

結果

| 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 |

スキーマ

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')
于 2012-09-17T18:47:59.720 に答える
1

これらの線に沿って何かが必要です。

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

OPがここですべての日付が必要であることを明確にしたので編集してください。彼の仕事がその日に終了する場合、私はEmplyeeをカウントから除外しましたが、以下のソリューションに変更t.[Date] < f.EndDate を含める場合は、更新されたソリューションです。t.[Date] <= f.EndDateさらにNULL、EndDateの値は、従業員がまだ部門で働いていることを意味すると思います。

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 )

これがSQLFiddlerのデモです。別の部門を追加し、それに従業員を追加しました。

http://sqlfiddle.com/#!3/5c4ec/1

于 2012-09-17T18:39:07.077 に答える