获取每个组和序列的开始和结束日期,由一个日期列派生
Get start and end date per group and sequence, derived by one date column
我有以下数据:
DECLARE @tbl TABLE (
ID VARCHAR(8)
,WeekDayName VARCHAR(15)
,StartDate VARCHAR(15)
,EndDate VARCHAR(15)
,A_Type VARCHAR(3)
,A_Days VARCHAR(10)
,A_Hours VARCHAR(10)
)
INSERT INTO @tbl (ID, WeekDayName, StartDate, EndDate, A_Type, A_Days, A_Hours)
VALUES
('150017', 'Monday', '2019-12-23', '2019-12-23', '430', 1.00, 8.20)
,('150017', 'Tuesday', '2019-12-24', '2019-12-24', '430', 1.00, 4.10)
,('150017', 'Friday', '2019-12-27', '2019-12-27', '430', 1.00, 8.20)
,('150017', 'Monday', '2019-12-30', '2019-12-30', '430', 1.00, 8.20)
,('150017', 'Tuesday', '2019-12-31', '2019-12-31', '430', 1.00, 4.10)
,('150035', 'Tuesday', '2019-03-12', '2019-03-12', '430', 0.66, 5.45)
,('150041', 'Thursday', '2019-01-17', '2019-01-17', '430', 1.00, 8.20)
,('150041', 'Tuesday', '2019-08-20', '2019-08-20', '430', 1.00, 8.20)
,('150041', 'Friday', '2019-08-21', '2019-08-21', '430', 1.00, 8.20)
,('150045', 'Monday', '2019-05-13', '2019-05-13', '430', 1.00, 8.20)
,('150045', 'Tuesday', '2019-05-14', '2019-05-14', '430', 1.00, 8.20)
,('150045', 'Wednesday', '2019-05-15', '2019-05-15', '430', 1.00, 8.20)
,('150045', 'Monday', '2019-11-25', '2019-11-25', '430', 1.00, 8.20)
,('150045', 'Tuesday', '2019-11-26', '2019-11-26', '430', 1.00, 8.20)
,('150045', 'Wednesday', '2019-11-27', '2019-11-27', '430', 1.00, 8.20)
,('150045', 'Thursday', '2019-11-28', '2019-11-28', '430', 1.00, 8.20)
,('150045', 'Friday', '2019-11-29', '2019-11-29', '430', 1.00, 8.20)
,('150046', 'Monday', '2019-03-11', '2019-03-11', '430', 1.00, 8.20)
,('150048', 'Tuesday', '2019-10-08', '2019-10-08', '430', 0.30, 2.50)
,('150048', 'Monday', '2019-10-28', '2019-10-28', '430', 1.00, 8.20)
StartDate 和 EndDate 始终相同,并且它们只是工作日(周一至周五)。 WeekDayName 是 StartDate 的名称。 ID 是一个整数。 A_Type(此处)始终为 430。A_Days(始终小于或等于 1),A_Hours(始终小于或等于 8.20)。
所需的输出是每个 ID 的开始日期、结束日期、[=33= 的总和]、[=34= 的总和]、SumDays。 SumDays 是 StartDate 和 EndDate 之间的工作日数。 EndDate 是按 ID 分组的 "block" 后续日期的最后一天。
例如
ID StartDate EndDate A_Days A_Hours SumDays
150017 2019-12-23 2019-12-31 5.00 32.80 5
150035 2019-03-12 2019-03-12 0.66 5.45 1
150041 2019-01-17 2019-01-17 1.00 8.20 1
150041 2019-08-20 2019-08-21 2.00 16.40 2
...
150041 有两条记录,因为后面有两个 "blocks" 日期。第一,2019-01-17,第二从2019-08-20到2019-08-21.
有人可以帮我吗? (作为奖励,如果也可以按 A_Type 列分组,那就太好了)。我无法让它工作。
感谢任何帮助。
提前谢谢你,
最佳
我了解到您想将具有相同 ID 和相邻日期(忽略周末)的记录组合在一起。这是一个差距和孤岛问题。
这是一种使用 lag()
检索之前的 endDate
并将其与当前的 startDate
进行比较的方法;每次日期不是 "adjacent" 时,都会开始一个新组(需要一些额外的逻辑来处理周五 > 周一的差距)。
select id, min(startDate) startDate, min(endDate) endDate, sum(a_days) a_days, sum(a_hours) a_hours, count(*) sumDays
from (
select
t.*,
sum(
case when
startDate = dateadd(d, 1, lagEndDate)
or (weekDayName = 'Monday' and startDate = dateadd(d, 3, lagEndDate))
then 0 else 1
end
) over (partition by id order by endDate) grp
from (
select t.*, lag(endDate) over(partition by id order by endDate) lagEndDate
from @tbl t
) t
) t
group by id, grp
对于您的示例数据,this produces:
id | startDate | endDate | a_days | a_hours | sumDays
:----- | :---------------------- | :---------------------- | :----- | :------ | ------:
150017 | 2019-12-23 00:00:00.000 | 2019-12-24 00:00:00.000 | 2.00 | 12.30 | 2
150017 | 2019-12-27 00:00:00.000 | 2019-12-31 00:00:00.000 | 3.00 | 20.50 | 3
150035 | 2019-03-12 00:00:00.000 | 2019-03-12 00:00:00.000 | 0.66 | 5.45 | 1
150041 | 2019-01-17 00:00:00.000 | 2019-01-17 00:00:00.000 | 1.00 | 8.20 | 1
150041 | 2019-08-20 00:00:00.000 | 2019-08-21 00:00:00.000 | 2.00 | 16.40 | 2
150045 | 2019-05-13 00:00:00.000 | 2019-05-15 00:00:00.000 | 3.00 | 24.60 | 3
150045 | 2019-11-25 00:00:00.000 | 2019-11-29 00:00:00.000 | 5.00 | 41.00 | 5
150046 | 2019-03-11 00:00:00.000 | 2019-03-11 00:00:00.000 | 1.00 | 8.20 | 1
150048 | 2019-10-08 00:00:00.000 | 2019-10-08 00:00:00.000 | 0.30 | 2.50 | 1
150048 | 2019-10-28 00:00:00.000 | 2019-10-28 00:00:00.000 | 1.00 | 8.20 | 1
我有以下数据:
DECLARE @tbl TABLE (
ID VARCHAR(8)
,WeekDayName VARCHAR(15)
,StartDate VARCHAR(15)
,EndDate VARCHAR(15)
,A_Type VARCHAR(3)
,A_Days VARCHAR(10)
,A_Hours VARCHAR(10)
)
INSERT INTO @tbl (ID, WeekDayName, StartDate, EndDate, A_Type, A_Days, A_Hours)
VALUES
('150017', 'Monday', '2019-12-23', '2019-12-23', '430', 1.00, 8.20)
,('150017', 'Tuesday', '2019-12-24', '2019-12-24', '430', 1.00, 4.10)
,('150017', 'Friday', '2019-12-27', '2019-12-27', '430', 1.00, 8.20)
,('150017', 'Monday', '2019-12-30', '2019-12-30', '430', 1.00, 8.20)
,('150017', 'Tuesday', '2019-12-31', '2019-12-31', '430', 1.00, 4.10)
,('150035', 'Tuesday', '2019-03-12', '2019-03-12', '430', 0.66, 5.45)
,('150041', 'Thursday', '2019-01-17', '2019-01-17', '430', 1.00, 8.20)
,('150041', 'Tuesday', '2019-08-20', '2019-08-20', '430', 1.00, 8.20)
,('150041', 'Friday', '2019-08-21', '2019-08-21', '430', 1.00, 8.20)
,('150045', 'Monday', '2019-05-13', '2019-05-13', '430', 1.00, 8.20)
,('150045', 'Tuesday', '2019-05-14', '2019-05-14', '430', 1.00, 8.20)
,('150045', 'Wednesday', '2019-05-15', '2019-05-15', '430', 1.00, 8.20)
,('150045', 'Monday', '2019-11-25', '2019-11-25', '430', 1.00, 8.20)
,('150045', 'Tuesday', '2019-11-26', '2019-11-26', '430', 1.00, 8.20)
,('150045', 'Wednesday', '2019-11-27', '2019-11-27', '430', 1.00, 8.20)
,('150045', 'Thursday', '2019-11-28', '2019-11-28', '430', 1.00, 8.20)
,('150045', 'Friday', '2019-11-29', '2019-11-29', '430', 1.00, 8.20)
,('150046', 'Monday', '2019-03-11', '2019-03-11', '430', 1.00, 8.20)
,('150048', 'Tuesday', '2019-10-08', '2019-10-08', '430', 0.30, 2.50)
,('150048', 'Monday', '2019-10-28', '2019-10-28', '430', 1.00, 8.20)
StartDate 和 EndDate 始终相同,并且它们只是工作日(周一至周五)。 WeekDayName 是 StartDate 的名称。 ID 是一个整数。 A_Type(此处)始终为 430。A_Days(始终小于或等于 1),A_Hours(始终小于或等于 8.20)。
所需的输出是每个 ID 的开始日期、结束日期、[=33= 的总和]、[=34= 的总和]、SumDays。 SumDays 是 StartDate 和 EndDate 之间的工作日数。 EndDate 是按 ID 分组的 "block" 后续日期的最后一天。
例如
ID StartDate EndDate A_Days A_Hours SumDays
150017 2019-12-23 2019-12-31 5.00 32.80 5
150035 2019-03-12 2019-03-12 0.66 5.45 1
150041 2019-01-17 2019-01-17 1.00 8.20 1
150041 2019-08-20 2019-08-21 2.00 16.40 2
...
150041 有两条记录,因为后面有两个 "blocks" 日期。第一,2019-01-17,第二从2019-08-20到2019-08-21.
有人可以帮我吗? (作为奖励,如果也可以按 A_Type 列分组,那就太好了)。我无法让它工作。
感谢任何帮助。
提前谢谢你,
最佳
我了解到您想将具有相同 ID 和相邻日期(忽略周末)的记录组合在一起。这是一个差距和孤岛问题。
这是一种使用 lag()
检索之前的 endDate
并将其与当前的 startDate
进行比较的方法;每次日期不是 "adjacent" 时,都会开始一个新组(需要一些额外的逻辑来处理周五 > 周一的差距)。
select id, min(startDate) startDate, min(endDate) endDate, sum(a_days) a_days, sum(a_hours) a_hours, count(*) sumDays
from (
select
t.*,
sum(
case when
startDate = dateadd(d, 1, lagEndDate)
or (weekDayName = 'Monday' and startDate = dateadd(d, 3, lagEndDate))
then 0 else 1
end
) over (partition by id order by endDate) grp
from (
select t.*, lag(endDate) over(partition by id order by endDate) lagEndDate
from @tbl t
) t
) t
group by id, grp
对于您的示例数据,this produces:
id | startDate | endDate | a_days | a_hours | sumDays :----- | :---------------------- | :---------------------- | :----- | :------ | ------: 150017 | 2019-12-23 00:00:00.000 | 2019-12-24 00:00:00.000 | 2.00 | 12.30 | 2 150017 | 2019-12-27 00:00:00.000 | 2019-12-31 00:00:00.000 | 3.00 | 20.50 | 3 150035 | 2019-03-12 00:00:00.000 | 2019-03-12 00:00:00.000 | 0.66 | 5.45 | 1 150041 | 2019-01-17 00:00:00.000 | 2019-01-17 00:00:00.000 | 1.00 | 8.20 | 1 150041 | 2019-08-20 00:00:00.000 | 2019-08-21 00:00:00.000 | 2.00 | 16.40 | 2 150045 | 2019-05-13 00:00:00.000 | 2019-05-15 00:00:00.000 | 3.00 | 24.60 | 3 150045 | 2019-11-25 00:00:00.000 | 2019-11-29 00:00:00.000 | 5.00 | 41.00 | 5 150046 | 2019-03-11 00:00:00.000 | 2019-03-11 00:00:00.000 | 1.00 | 8.20 | 1 150048 | 2019-10-08 00:00:00.000 | 2019-10-08 00:00:00.000 | 0.30 | 2.50 | 1 150048 | 2019-10-28 00:00:00.000 | 2019-10-28 00:00:00.000 | 1.00 | 8.20 | 1