使用红移。我有一个包含以下字段的表:
Column: Type:
department | varchar
employee_ID | varchar
event | varchar
date | date
一个日期表,只有一个字段并列出所有日期。 每个部门都有几个部门有员工。 "事件"字段有两个可能的值:JOIN或LEAVE。加入记录是他们加入公司/部门的日期,LEAVE记录是他们离开公司/部门的日期。它看起来像这样:
department employee_id event date
marketing 001 JOIN 6/17/2017
marketing 002 JOIN 6/19/2017
marketing 002 LEAVE 6/20/2017
marketing 001 LEAVE 6/22/2017
我想制作一个每天都列出的表格(同样我也有一张包含所有日期的表格),以及当他们被雇佣时的值为1,当他们不是所有员工时,值为0。这看起来像这样:
date department employee_id employed
6/17/2017 marketing 001 1
6/18/2017 marketing 001 1
6/19/2017 marketing 001 1
6/19/2017 marketing 002 1
6/20/2017 marketing 001 1
6/20/2017 marketing 002 1
6/21/2017 marketing 001 1
6/22/2017 marketing 001 1
想我可能需要创建一个具有开始日期并在同一行中保留日期的新表?为此我可以使用case语句和分区来获取第一个和最后一个日期,但不知道从那里去哪里...也许是一个计数表?该查询可能看起来像这样,但仍然无法获得所需的结果:
select
department,
employee_id,
CASE WHEN ROW_NUMBER() OVER (PARTITION BY employee_id ORDER BY date ASC) = 1 THEN date
ELSE NULL
END AS join_date,
CASE WHEN ROW_NUMBER() OVER (PARTITION BY employee_id ORDER BY date DESC) = 1 THEN date
ELSE NULL
END AS leave_date
from table1
答案 0 :(得分:-1)
您需要在日期表和包含加入和离开日期的表格之间使用CROSS JOIN
。
仅限示例数据。您可以使用现有的表格。
CREATE TEMP TABLE dim_date (dt_val)
AS SELECT '2017-06-16'::date dt_val
UNION ALL SELECT '2017-06-17'::date dt_val
UNION ALL SELECT '2017-06-18'::date dt_val
UNION ALL SELECT '2017-06-19'::date dt_val
UNION ALL SELECT '2017-06-20'::date dt_val
UNION ALL SELECT '2017-06-21'::date dt_val
UNION ALL SELECT '2017-06-22'::date dt_val
UNION ALL SELECT '2017-06-23'::date dt_val
;
CREATE TEMP TABLE empl_event (department, employee_id, event, event_dt)
AS SELECT 'marketing' department, 1 employee_id, 'JOIN' event, '2017-06-17'::date event_dt
UNION ALL SELECT 'marketing' department, 2 employee_id, 'JOIN' event, '2017-06-19'::date event_dt
UNION ALL SELECT 'marketing' department, 2 employee_id, 'LEAVE' event, '2017-06-20'::date event_dt
UNION ALL SELECT 'marketing' department, 1 employee_id, 'LEAVE' event, '2017-06-22'::date event_dt
;
逻辑步骤1:将JOIN
和LEAVE
事件转换为第1行的日期
CREATE TEMP TABLE empl_period (department, employee_id, join_dt, leave_dt)
AS
SELECT department
,employee_id
,MAX(CASE WHEN event = 'JOIN' THEN event_dt ELSE NULL END) join_dt
,MAX(CASE WHEN event = 'LEAVE' THEN event_dt ELSE NULL END) leave_dt
FROM empl_event
GROUP BY 1,2
;
逻辑步骤2:使用CROSS JOIN
为每个可能的员工日期组合创建一行,如果日期介于employed
和join_dt
之间,则将leave_dt
设置为1。
SELECT emp.department
,emp.employee_id
,ddt.dt_val
,CASE WHEN ddt.dt_val BETWEEN emp.join_dt AND emp.leave_dt THEN 1 ELSE 0 END employed
FROM empl_period emp
CROSS JOIN dim_date ddt
ORDER BY 1,2,3
;
输出示例数据
department | employee_id | dt_val | employed
------------+-------------+------------+----------
marketing | 1 | 2017-06-16 | 0
marketing | 1 | 2017-06-17 | 1
marketing | 1 | 2017-06-18 | 1
marketing | 1 | 2017-06-19 | 1
marketing | 1 | 2017-06-20 | 1
marketing | 1 | 2017-06-21 | 1
marketing | 1 | 2017-06-22 | 1
marketing | 1 | 2017-06-23 | 0
marketing | 2 | 2017-06-16 | 0
marketing | 2 | 2017-06-17 | 0
marketing | 2 | 2017-06-18 | 0
marketing | 2 | 2017-06-19 | 1
marketing | 2 | 2017-06-20 | 1
marketing | 2 | 2017-06-21 | 0
marketing | 2 | 2017-06-22 | 0
marketing | 2 | 2017-06-23 | 0
答案 1 :(得分:-1)
您可以使用以下SQL来使用日期和日期
来扩展日期DECLARE @dateranges TABLE (employee_id VARCHAR(4),
department VARCHAR(20),
join_date DATE,
leave_date DATE)
INSERT @dateranges SELECT employee_id,
department,
MIN(event_date) join_date,
MAX(event_date) leave_date
FROM employment
GROUP BY employee_id,
department;
WITH cte (dt, dept, id, emd) AS
(
SELECT tbl.join_date AS dt,
tbl.department AS dept,
tbl.employee_id AS employee_id,
1 AS emd
FROM @dateranges tbl
UNION ALL
SELECT DATEADD(DAY, 1, cte.dt) AS dt,
tbl.department AS dept,
tbl.employee_id AS employee_id,
1 AS emp
FROM cte
INNER JOIN @dateranges tbl
ON cte.id = tbl.employee_id
AND cte.dept = tbl.department
WHERE cte.dt < tbl.leave_date
)
SELECT dt AS date,
dept AS department,
id AS employee_id,
emd AS employed
FROM cte
ORDER BY dt, id
结果:
date department employee_id employed
2017-06-17 marketing 001 1
2017-06-18 marketing 001 1
2017-06-19 marketing 001 1
2017-06-19 marketing 002 1
2017-06-20 marketing 001 1
2017-06-20 marketing 002 1
2017-06-21 marketing 001 1
2017-06-22 marketing 001 1