在一个查询中聚合N次(按分区)? CTE?

时间:2011-08-04 17:38:58

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

净雇用日期范围

我有一组包含这些字段的员工数据。如果终止日期仍然有效,则终止日期为空。

id   |    hire date    | termination date
1           7/25/11     |         null
2           12/01/10    |  7/30/11
3           7/20        |  null
4           7/16        | 7/29/11

我需要得到的是13周的滚动时间:

week ending date     Net hires
07-17                   1
07-24                   1
07-31          -1

...

我已经开始使用CTE然后使用工会,因为我放弃了试图找出更好的方法。我也必须为其他一些领域做这个,所以也许有更好的方法,也许使用pivot / unpivot?

我现在所拥有的粗略伪代码。

;with foo
as
(
select *
from employee
--joins and conditions
)
select @report_date, sum(case when hire date > report_date-7 and hire_date < report_date then 1 else 0 end)(

... etc

我会照顾日期,之后不会招聘/终止。

1 个答案:

答案 0 :(得分:4)

您将所有这些UNION与硬编码列放在一起这一事实应该告诉您,您在某个地方错过了一个集合。在这种情况下,这是几周。将它们放在一个表中(永久,临时或通过CTE虚拟),这个查询变得微不足道。

SELECT
    WKS.start_date,
    COUNT(E.employee_id)
FROM
    Report_Weeks WKS
LEFT OUTER JOIN Employees E ON
    E.hire_date > WKS.start_date AND
    E.hire_date < WKS.end_date
GROUP BY
    WKS.start_date
ORDER BY
    WKS.start_date

既然你提到“网络”雇用我猜你也想要在终端工作。您可以将其转换为SUM(CASE...),其中您为新员工使用1,为那个星期之外的人使用0,或者在同一周内雇用然后被解雇,以及-1用于终止。

正如JNK所指出的那样,在CASE声明中对订单事宜进行了规定。此外,您可以使用ELSE来处理0值。我会建议这样的事情:

CASE
    WHEN
        E.hire_date BETWEEN WKS.start_date AND WKS.end_date AND
        E.termination_date > WKS.end_date THEN 1
    WHEN
        E.termination_date BETWEEN WKS.start_date AND WKS.end_date AND
        E.hire_date < WKS.end_date THEN -1
    ELSE 0
END

由于我使用了BETWEEN,因此您需要确保一周的开始日期与上一周的结束日期不完全相同。