Получить начальную и конечную дату для группы и последовательности, полученную по одному столбцу даты - PullRequest
0 голосов
/ 01 апреля 2020

У меня есть данные ниже:

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).

Требуемый вывод для каждого идентификатора - StartDate, EndDate, Sum of A_Days, Сумма A_Hours, SumDays. SumDays - это количество рабочих дней между StartDate и EndDate. EndDate - это день, который является последней датой «блока» следующих дат, сгруппированных по идентификатору.

Например,

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 имеет две записи, так как их две " блоки "следующих дат. Первый, 2019-01-17, и секунды с 2019-08-20 по 2019-08-21.

Может кто-нибудь помочь мне с этим? (В качестве бонуса было бы здорово, если бы можно было группировать также по столбцу A_Type). Я не мог заставить его работать.

Любая помощь приветствуется.

Заранее спасибо,

Лучший

1 Ответ

1 голос
/ 01 апреля 2020

Я понимаю, что вы хотите сгруппировать записи с одинаковым идентификатором и смежными днями (без учета выходных). Это проблема пробелов и островков.

Вот один подход, который использует lag() для извлечения предыдущего endDate и сравнения его с текущим startDate; каждый раз, когда даты не являются «смежными», начинается новая группа (для обработки разрыва пятница> понедельник требуется небольшая дополнительная логика c).

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

Для ваших выборочных данных это производит :

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
...