Sql 确定连续和独立的PTO天数
根据反馈,我正在重组我的问题 我正在Presto数据库上使用SQL 我的目标是报告自2018年初以来连续几天休PTO或病假的员工。我所期望的输出将包含员工花费的各个时间岛以及开始和结束日期,大致如下: 我使用的主要表格是d_employee_time_off 只有两次休假类型名称:PTO和病假 ds是一个日期戳,我使用最新的ds(通常是当前日期) 我有权访问名为d_date的日期表 我可以加入d_employee_time_off.time_off_date=d_date.full_date上的表Sql 确定连续和独立的PTO天数,sql,presto,Sql,Presto,根据反馈,我正在重组我的问题 我正在Presto数据库上使用SQL 我的目标是报告自2018年初以来连续几天休PTO或病假的员工。我所期望的输出将包含员工花费的各个时间岛以及开始和结束日期,大致如下: 我使用的主要表格是d_employee_time_off 只有两次休假类型名称:PTO和病假 ds是一个日期戳,我使用最新的ds(通常是当前日期) 我有权访问名为d_date的日期表 我可以加入d_employee_time_off.time_off_date=d_date.full_dat
我希望我已经以一种可以理解的方式组织了这个问题。我认为这里需要的是将休假资料加入日历表 在下面的示例解决方案中,我正在“动态”生成这个,但我认为您对此有自己的解决方案。同样在我的示例中,我使用了字符串“Monday”并从该字符串向后移动(或者,您可以使用“Friday”并向前移动)。我对依赖语言的解决方案不感兴趣,但由于我不是Presto用户,所以无法在Presto上测试任何东西。因此,下面的示例使用了您自己的一些逻辑,但使用SQL Server语法,我相信您可以将其转换为Presto: 查询:
;WITH
Digits AS (
SELECT 0 AS digit UNION ALL
SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL
SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL
SELECT 9
)
, cal AS (
SELECT
ca.number
, dateadd(day,ca.number,'20180101') as cal_date
, datename(weekday,dateadd(day,ca.number,'20180101')) weekday
FROM Digits [1s]
CROSS JOIN Digits [10s]
CROSS JOIN Digits [100s] /* add more like this as needed */
cross apply (
SELECT
[1s].digit
+ [10s].digit * 10
+ [100s].digit * 100 /* add more like this as needed */
AS number
) ca
)
, time_off AS (
select
*
from cal
inner join mytable t on (cal.cal_date = t.time_off_date and cal.weekday <> 'Monday')
or (cal.cal_date between dateadd(day,-2,t.time_off_date)
and t.time_off_date and datename(weekday,t.time_off_date) = 'Monday')
)
, starting_points AS (
SELECT
employee_id,
cal_date,
dense_rank() OVER(partition by employee_id
ORDER BY
time_off_date
) AS rownum
FROM
time_off A
WHERE
NOT EXISTS (
SELECT
*
FROM
time_off B
WHERE
B.employee_id = A.employee_id
AND B.cal_date = DATEADD(day, -1, A.cal_date)
)
)
, ending_points AS (
SELECT
employee_id,
cal_date,
dense_rank() OVER(partition by employee_id
ORDER BY
time_off_date
) AS rownum
FROM
time_off A
WHERE
NOT EXISTS (
SELECT
*
FROM
time_off B
WHERE
B.employee_id = A.employee_id
AND B.cal_date = DATEADD(day, 1, A.cal_date)
)
)
SELECT
S.employee_id,
S.cal_date AS start_range,
E.cal_date AS end_range
FROM
starting_points S
JOIN
ending_points E
ON E.employee_id = S.employee_id
AND E.rownum = S.rownum
order by employee_id
, start_range
见:
@KenWhite这是一个“孤岛”要求,常规的min()max()和group by无法满足。请您提供源数据作为示例,而不是向我们显示一些查询输出(这是不正确的)。查看您尝试过的查询也很有用。@Used\u By\u已使用源数据实际上只是员工id、类型(仅为PTO或病假)、日期和休假时间(以天为单位)(始终为1)。我加入了一个日期表以获取日期名称,并使用超前和滞后函数来获取上一个和未来的日期。您认为这个问题是一个“孤岛”要求,这让我读了一些很好的书,所以我将继续讨论这个问题,并在我试图找到解决方案时进行更新。它写得非常好,因为它包括一个自包含的表结构(DDL)、填充这些表的数据,以及尝试根据表检索数据和预期输出的查询。换句话说,这是一个完整的过程。您在问题中提供这些相同的工件将大大有助于其他人帮助您解决问题。您还可以将其用于DDL和数据。谢谢@Igor。我将看看这个问题和您提供的其他链接。希望您现在能够看到提供示例数据(而不是查询结果)的必要性,以及使用一些日历表的有用性。提供样品可以更快地回答您的问题。非常感谢。我是一个noob,仍在学习,所以请原谅我的问题结构不合理(我相信我是在重组我的问题,因为你提供了答案)。我真的很感谢你的帮助,我保证会努力变得更好。一点也不,你的问题一点也不差,只是指出了可能的改进——这最终也会对你有利。然而,不要使用数据的图像,这不是很友好的使用,因为它需要有人转录它。简单的文本表要好得多。图像如果我的答案是查询的图像:)。我也不知道你为什么删除了你的查询,那应该留在问题中。谢谢。我将重新编辑问题,因为我希望能够提出好的问题。再次感谢您,我非常感谢您的帮助。:)好的,但我会保留您阅读这些内容的努力,并/或在您接下来的问题中付诸实践。
employee_id start_range end_range
1 200035 02.01.2018 02.01.2018
2 200035 20.04.2018 27.04.2018
3 200037 27.01.2018 29.01.2018
4 200037 31.03.2018 02.04.2018
CREATE TABLE mytable(
ID INT NOT NULL
,employee_id INTEGER NOT NULL
,type VARCHAR(3) NOT NULL
,time_off_date DATE NOT NULL
,time_off_in_days INT NOT NULL
);
INSERT INTO mytable(id,employee_id,type,time_off_date,time_off_in_days) VALUES (1,200035,'PTO','2018-01-02',1);
INSERT INTO mytable(id,employee_id,type,time_off_date,time_off_in_days) VALUES (2,200035,'PTO','2018-04-20',1);
INSERT INTO mytable(id,employee_id,type,time_off_date,time_off_in_days) VALUES (3,200035,'PTO','2018-04-23',1);
INSERT INTO mytable(id,employee_id,type,time_off_date,time_off_in_days) VALUES (4,200035,'PTO','2018-04-24',1);
INSERT INTO mytable(id,employee_id,type,time_off_date,time_off_in_days) VALUES (5,200035,'PTO','2018-04-25',1);
INSERT INTO mytable(id,employee_id,type,time_off_date,time_off_in_days) VALUES (6,200035,'PTO','2018-04-26',1);
INSERT INTO mytable(id,employee_id,type,time_off_date,time_off_in_days) VALUES (7,200035,'PTO','2018-04-27',1);
INSERT INTO mytable(id,employee_id,type,time_off_date,time_off_in_days) VALUES (8,200037,'PTO','2018-01-29',1);
INSERT INTO mytable(id,employee_id,type,time_off_date,time_off_in_days) VALUES (9,200037,'PTO','2018-04-02',1);