在SQL中将用户分组90天

时间:2011-09-01 18:51:35

标签: sql sql-server sql-server-2008

我需要让最近90名雇佣的员工在过去4周内每次都被终止。这是一份滚动报告。

员工表就像这样:

id      hired_date       term_date
3        07/1/2011        09/01/2011
4        07/18/2011        NULL    (NULL means still active) 
5        01/20/2009       08/23/2011
6        05/30/2011       8/22/2011
7        7/20/2011        7/23/2011

报告将采用这种格式。 Id#4,5将被忽略,因为#4仍处于活动状态,#5在90天之前被雇用。

Week ending     Terminated employees hired within past 90 days
09/03/2011        2   --(id 3,7)
8/27/2011         2   --(id 6,7)
..
..
  • 因此,9/03的第一行是雇用的终止雇员人数 过去90天的9/03/2011(回到06/05/2011)。这不包括身份#6,因为员工是在6/05之前被雇用的。
  • 8/27周的第二行是相同的,但是从8/27到5/29不等。

我有一个日期表,但它只包含week_start_date,week_end_date和week_number。我是否需要创建一个包含90天期限的文件?

我被困在过去90天内我只能为员工做这件事,然后计算过去4周的每一天。

SQL Server 2008

修改 我想我很亲密。我正在测试它。 All_termed_employees是任何日期范围内已终止员工的列表。周表现在包含与之相关的每周的ninety_begin_date和ninety_end_date。

select wk.ninety_end, count(h.id)
FROM @weeks wk
LEFT JOIN all_termed_employees h 
    ON h.hire_date <= wk.ninety_end and h.hire_date >= wk.ninety_begin
          and .termination_date <= wk.ninety_end AND h.termination_date >= wk.ninety_begin
ORDER BY d.id
GROUP BY wk.ninety_end

2 个答案:

答案 0 :(得分:4)

;WITH n(n) AS 
      -- just 4 rows - makes it easy to extend to 5 weeks, 6 weeks, etc.
      ( SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 ),

d(dt) AS
      -- single row with the end of the current week
      -- this could be a variable but I get a lot of flack for not inlining
      ( SELECT dt = CONVERT(DATE, DATEADD(DAY, 
          7-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP))),

w(dt) AS 
      -- get the end of each week based on the rows in n
      ( SELECT DATEADD(WEEK, -n.n, d.dt) FROM n CROSS JOIN d )

SELECT 
    w.dt, SUM(CASE 
    WHEN e.term_date >= DATEADD(DAY, -90, w.dt) 
    AND e.term_date  <  DATEADD(DAY, 1,   w.dt) 
    AND e.hired_date >= DATEADD(DAY, -90, w.dt) 
    AND e.hired_date <  DATEADD(DAY, 1,   w.dt)  
    THEN 1 ELSE 0 END)
FROM dbo.Employees AS e
CROSS JOIN w
GROUP BY w.dt
ORDER BY w.dt DESC; 

答案 1 :(得分:2)

这样的事情怎么样?

EMP模拟您的员工表。 PAST_FOUR_WEEKS是一个简单的4行内存表,用于标识报告周期。然后我计算雇用和期限日期之间的差异,如果它小于或等于90,我们将其计为1(达到阈值)或0)。然后,我将在给定时间段内满足所有阈值的总和

; WITH EMP (id, hired_date, term_date) AS
(
    select 3, CAST('2011-07-01' AS datetime), CAST('2011-09-01' AS datetime)
    union all select 4, '2011-06-18', null
    union all select 5, '01/20/2009','08/23/2011'
    union all select 6, '05/30/2011','8/22/2011'
    union all select 7, '7/20/2011','7/23/2011'
)
, PAST_FOUR_WEEKS (period, period_rank) AS
(
    -- magic goes here to determine end of week
    SELECT CURRENT_TIMESTAMP, 1
    UNION ALL SELECT dateadd(week, -1, CURRENT_TIMESTAMP) , 2
    UNION ALL SELECT dateadd(week, -2, CURRENT_TIMESTAMP) , 3
    UNION ALL SELECT dateadd(week, -3, CURRENT_TIMESTAMP) , 4
)
, HIRED_TERMED_DIFF AS
(
    SELECT
        *
    ,   DATEDIFF(d, E.hired_date, coalesce(E.term_date, '9999-12-31T23:59:59.997')) AS duration
    ,   CASE WHEN DATEDIFF(d, E.hired_date, coalesce(E.term_date, '9999-12-31T23:59:59.997')) < 91 THEN 1 ELSE 0 END AS threshold_met
    FROM
        EMP E 
)
SELECT
    PFW.period
,   SUM(HTD.threshold_met) AS [Terminated employees hired within past 90 days]
FROM 
    PAST_FOUR_WEEKS PFW
    LEFT OUTER JOIN
        HIRED_TERMED_DIFF HTD
        ON HTD.hired_date BETWEEN DATEADD(day, -90, PFW.period) AND PFW.period
GROUP BY
    PFW.period
ORDER BY
    1 DESC
,   2

示例输出

period                    Terminated employees hired within past 90 days
2011-09-01 14:46:29.243   2
2011-08-25 14:46:29.243   3
2011-08-18 14:46:29.243   3
2011-08-11 14:46:29.243   3