Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Объединить последовательные диапазоны с датами  [new]
Mikrosoftov
Member

Откуда:
Сообщений: 10
прошу помочь.
Нужно в таблице в которой идут подряд даты, объединить записи таким образом чтобы в диапазон дат попадали все значения n1 и n2 с одинаковым значением c1. Пример ниже:
Из такой таблицы:
d1 d2 n1 n2 c1
30.06.2014 30.06.2014 2 15 359
30.06.2014 30.06.2014 16 22 409
30.06.2014 30.06.2014 23 31 459
01.07.2014 01.07.2014 2 15 359
01.07.2014 01.07.2014 16 22 409
01.07.2014 01.07.2014 23 31 459
02.07.2014 02.07.2014 2 15 359
02.07.2014 02.07.2014 16 22 409
02.07.2014 02.07.2014 23 31 459
03.07.2014 03.07.2014 2 4 359
03.07.2014 03.07.2014 5 5 389
03.07.2014 03.07.2014 6 15 359
03.07.2014 03.07.2014 16 22 409
03.07.2014 03.07.2014 23 31 459
04.07.2014 04.07.2014 2 4 359
04.07.2014 04.07.2014 5 5 389
04.07.2014 04.07.2014 6 15 359
04.07.2014 04.07.2014 16 22 409
04.07.2014 04.07.2014 23 31 459
05.07.2014 05.07.2014 2 4 359
05.07.2014 05.07.2014 5 5 389
05.07.2014 05.07.2014 6 15 359
05.07.2014 05.07.2014 16 22 409
05.07.2014 05.07.2014 23 31 459
06.07.2014 06.07.2014 2 4 359
06.07.2014 06.07.2014 5 5 389
06.07.2014 06.07.2014 6 15 359
06.07.2014 06.07.2014 16 22 409
06.07.2014 06.07.2014 23 31 459
07.07.2014 07.07.2014 2 15 339
07.07.2014 07.07.2014 16 22 389
07.07.2014 07.07.2014 23 31 439
08.07.2014 08.07.2014 2 15 339
08.07.2014 08.07.2014 16 22 389
08.07.2014 08.07.2014 23 31 439
09.07.2014 09.07.2014 2 15 339
09.07.2014 09.07.2014 16 22 389
09.07.2014 09.07.2014 23 31 439
10.07.2014 10.07.2014 2 15 339
10.07.2014 10.07.2014 16 22 389
10.07.2014 10.07.2014 23 31 439

Нужно получить такую:
d1 d2 n1 n2 c1
30.06.2014 02.07.2014 2 15 359
30.06.2014 02.07.2014 16 22 409
30.06.2014 02.07.2014 23 31 459
03.07.2014 06.07.2014 2 4 359
03.07.2014 06.07.2014 5 5 389
03.07.2014 06.07.2014 6 15 359
03.07.2014 06.07.2014 16 22 409
03.07.2014 06.07.2014 23 31 459
07.07.2014 10.07.2014 2 15 339
07.07.2014 10.07.2014 16 22 389
07.07.2014 10.07.2014 23 31 439


Нашел на форуме одно из решений, объединил, но получается не совсем то что хотелось
Вот что получается:
d1 d2 n1 n2 c1
30.06.2014 02.07.2014 2 15 359
30.06.2014 06.07.2014 16 22 409
30.06.2014 06.07.2014 23 31 459
03.07.2014 06.07.2014 2 4 359
03.07.2014 06.07.2014 5 5 389
03.07.2014 06.07.2014 6 15 359
07.07.2014 10.07.2014 2 15 339
07.07.2014 10.07.2014 16 22 389
07.07.2014 10.07.2014 23 31 439

Не нравится то, что значения n1 и n2 попадают в разные диапазоны, а хотелось бы чтобы в один диапазон дат попадали все значения n1 и n2 от 2 до 31 как в примере выше.

Две недели ломаю голову. Заранее благодарю за помощь.
Ниже таблица со значениями, а также решение, которое дает результат, который меня не удовлетворяет)):
------------------------------------------------------------------
create table #sss1 (id int identity, d1 date, d2 date, n1 int, n2 int, c1 int)
insert into #sss1 (d1, d2, c1, n1, n2) values

('2014-06-30', '2014-06-30', 359, 2, 15),
('2014-06-30', '2014-06-30', 409, 16, 22),
('2014-06-30', '2014-06-30', 459, 23, 31),
('2014-07-01', '2014-07-01', 359, 2, 15),
('2014-07-01', '2014-07-01', 409, 16, 22),
('2014-07-01', '2014-07-01', 459, 23, 31),
('2014-07-02', '2014-07-02', 359, 2, 15),
('2014-07-02', '2014-07-02', 409, 16, 22),
('2014-07-02', '2014-07-02', 459, 23, 31),
('2014-07-03', '2014-07-03', 359, 2, 4),
('2014-07-03', '2014-07-03', 389, 5, 5),
('2014-07-03', '2014-07-03', 359, 6, 15),
('2014-07-03', '2014-07-03', 409, 16, 22),
('2014-07-03', '2014-07-03', 459, 23, 31),
('2014-07-04', '2014-07-04', 359, 2, 4),
('2014-07-04', '2014-07-04', 389, 5, 5),
('2014-07-04', '2014-07-04', 359, 6, 15),
('2014-07-04', '2014-07-04', 409, 16, 22),
('2014-07-04', '2014-07-04', 459, 23, 31),
('2014-07-05', '2014-07-05', 359, 2, 4),
('2014-07-05', '2014-07-05', 389, 5, 5),
('2014-07-05', '2014-07-05', 359, 6, 15),
('2014-07-05', '2014-07-05', 409, 16, 22),
('2014-07-05', '2014-07-05', 459, 23, 31),
('2014-07-06', '2014-07-06', 359, 2, 4),
('2014-07-06', '2014-07-06', 389, 5, 5),
('2014-07-06', '2014-07-06', 359, 6, 15),
('2014-07-06', '2014-07-06', 409, 16, 22),
('2014-07-06', '2014-07-06', 459, 23, 31),
('2014-07-07', '2014-07-07', 339, 2, 15),
('2014-07-07', '2014-07-07', 389, 16, 22),
('2014-07-07', '2014-07-07', 439, 23, 31),
('2014-07-08', '2014-07-08', 339, 2, 15),
('2014-07-08', '2014-07-08', 389, 16, 22),
('2014-07-08', '2014-07-08', 439, 23, 31),
('2014-07-09', '2014-07-09', 339, 2, 15),
('2014-07-09', '2014-07-09', 389, 16, 22),
('2014-07-09', '2014-07-09', 439, 23, 31),
('2014-07-10', '2014-07-10', 339, 2, 15),
('2014-07-10', '2014-07-10', 389, 16, 22),
('2014-07-10', '2014-07-10', 439, 23, 31)

select * from #sss1
--drop table #sss1
------------------------------------------------------------------
declare @t table (d1 Date, d2 Date, n1 int, n2 int, c1 int)
insert into @t (n1, n2, c1, d1, d2)

SELECT
T.n1,
T.n2,
T.c1,
T.d1,
(
SELECT MIN(TT.d2)
FROM #sss1 TT
WHERE TT.c1=T.c1 AND TT.d1>=T.d2
AND NOT EXISTS(SELECT * FROM #sss1 TTT WHERE TTT.c1=TT.c1 AND
TTT.n1=TT.n1 AND
TTT.n2=TT.n2 AND
TTT.d1=dateadd(day,+1,cast(substring(convert(nvarchar(100), TT.d2, 120),1,10) as datetime)))
) d2
FROM #sss1 T
WHERE NOT EXISTS(SELECT * FROM #sss1 TT WHERE TT.c1=T.c1 AND
TT.n1=T.n1 AND
TT.n2=T.n2 AND
TT.d2=dateadd(day,-1,cast(substring(convert(nvarchar(100), T.d1, 120),1,10) as datetime)))

SELECT * FROM @t ORDER BY d1, n1

--drop table #sss1
------------------------------------------------------------------
6 апр 14, 01:47    [15838613]     Ответить | Цитировать Сообщить модератору
 Re: Объединить последовательные диапазоны с датами  [new]
invm
Member

Откуда: Москва
Сообщений: 9406
На основании чего из
d1d2n1n2c1
2014-06-302014-06-301622409
2014-07-012014-07-011622409
2014-07-022014-07-021622409
2014-07-032014-07-031622409
2014-07-042014-07-041622409
2014-07-052014-07-051622409
2014-07-062014-07-061622409

должно получиться
d1d2n1n2c1
2014-06-302014-07-021622409
2014-07-032014-07-061622409

а не
d1d2n1n2c1
2014-06-302014-07-061622409

?
6 апр 14, 10:52    [15838892]     Ответить | Цитировать Сообщить модератору
 Re: Объединить последовательные диапазоны с датами  [new]
Mikrosoftov
Member

Откуда:
Сообщений: 10
на основании первого возникшего периода
d1 d2 n1 n2 c1
30.06.2014 02.07.2014 2 15 359
6 апр 14, 10:59    [15838895]     Ответить | Цитировать Сообщить модератору
 Re: Объединить последовательные диапазоны с датами  [new]
aleks2
Guest
Mikrosoftov
на основании первого возникшего периода
d1 d2 n1 n2 c1
30.06.2014 02.07.2014 2 15 359


1. Начало интервала непрерывности наступает тогда, когда НЕМА предшествующей записи.
2. Конец интервала непрерывности наступает тогда, когда нема следующей записи.
3. Таких концов одинаковое количество и оне следуют так (начало1, конец1, начало2, конец2).
4. Больше ничего не надо.
6 апр 14, 14:08    [15839227]     Ответить | Цитировать Сообщить модератору
 Re: Объединить последовательные диапазоны с датами  [new]
Mikrosoftov
Member

Откуда:
Сообщений: 10
aleks2,

а в виде кода можно?, а то че-то не получается((
6 апр 14, 17:52    [15839817]     Ответить | Цитировать Сообщить модератору
 Re: Объединить последовательные диапазоны с датами  [new]
aleks2
Guest
declare @sss1 table  (id int identity, d1 date, d2 date, n1 int, n2 int, c1 int)
insert into @sss1 (d1, d2, c1, n1, n2) values
('2014-06-30', '2014-06-30', 359, 2, 15),
('2014-06-30', '2014-06-30', 409, 16, 22),
('2014-06-30', '2014-06-30', 459, 23, 31),
('2014-07-01', '2014-07-01', 359, 2, 15),
('2014-07-01', '2014-07-01', 409, 16, 22),
('2014-07-01', '2014-07-01', 459, 23, 31),
('2014-07-02', '2014-07-02', 359, 2, 15),
('2014-07-02', '2014-07-02', 409, 16, 22),
('2014-07-02', '2014-07-02', 459, 23, 31),
('2014-07-03', '2014-07-03', 359, 2, 4),
('2014-07-03', '2014-07-03', 389, 5, 5),
('2014-07-03', '2014-07-03', 359, 6, 15),
('2014-07-03', '2014-07-03', 409, 16, 22),
('2014-07-03', '2014-07-03', 459, 23, 31),
('2014-07-04', '2014-07-04', 359, 2, 4),
('2014-07-04', '2014-07-04', 389, 5, 5),
('2014-07-04', '2014-07-04', 359, 6, 15),
('2014-07-04', '2014-07-04', 409, 16, 22),
('2014-07-04', '2014-07-04', 459, 23, 31),
('2014-07-05', '2014-07-05', 359, 2, 4),
('2014-07-05', '2014-07-05', 389, 5, 5),
('2014-07-05', '2014-07-05', 359, 6, 15),
('2014-07-05', '2014-07-05', 409, 16, 22),
('2014-07-05', '2014-07-05', 459, 23, 31),
('2014-07-06', '2014-07-06', 359, 2, 4),
('2014-07-06', '2014-07-06', 389, 5, 5),
('2014-07-06', '2014-07-06', 359, 6, 15),
('2014-07-06', '2014-07-06', 409, 16, 22),
('2014-07-06', '2014-07-06', 459, 23, 31),
('2014-07-07', '2014-07-07', 339, 2, 15),
('2014-07-07', '2014-07-07', 389, 16, 22),
('2014-07-07', '2014-07-07', 439, 23, 31),
('2014-07-08', '2014-07-08', 339, 2, 15),
('2014-07-08', '2014-07-08', 389, 16, 22),
('2014-07-08', '2014-07-08', 439, 23, 31),
('2014-07-09', '2014-07-09', 339, 2, 15),
('2014-07-09', '2014-07-09', 389, 16, 22),
('2014-07-09', '2014-07-09', 439, 23, 31),
('2014-07-10', '2014-07-10', 339, 2, 15),
('2014-07-10', '2014-07-10', 389, 16, 22),
('2014-07-10', '2014-07-10', 439, 23, 31)

select * from @sss1 order by c1, d1 asc
------------------------------------------------------------------
declare @b table (id int, d1 date, d2 date, n1 int, n2 int, c1 int, n int identity primary key clustered);

insert @b
  select t.id, t.d1, t.d2, t.n1, t.n2, t.c1 
    from @sss1 t left outer join @sss1 tt on t.n1 = tt.n1 and t.n2 = tt.n2 and t.c1 = tt.c1 and t.id <> tt.id and t.d1 = dateadd(day, 1, tt.d2)
    where tt.id is null
    order by t.n1, t.n2, t.c1, t.d1 ASC;
    
select * from @b    

declare @e table (id int, d1 date, d2 date, n1 int, n2 int, c1 int, n int identity primary key clustered);
insert @e
  select t.id, t.d1, t.d2, t.n1, t.n2, t.c1 
    from @sss1 t left outer join @sss1 tt on t.n1 = tt.n1 and t.n2 = tt.n2 and t.c1 = tt.c1 and t.id <> tt.id and t.d2 = dateadd(day, -1, tt.d1)
    where tt.id is null
    order by t.n1, t.n2, t.c1, t.d1 ASC;
    
select * from @e

select b.d1, e.d2, b.n1, b.n2, b.c1
  from @b b inner join @e e on b.n = e.n
7 апр 14, 08:43    [15841219]     Ответить | Цитировать Сообщить модератору
 Re: Объединить последовательные диапазоны с датами  [new]
Mikrosoftov
Member

Откуда:
Сообщений: 10
aleks2,

Спасибо за помощь, но результат получается точно такой же как и при запуске моего скрипта
т.е. так:
d1 d2 n1 n2 c1
30.06.2014 02.07.2014 2 15 359
30.06.2014 06.07.2014 16 22 409
30.06.2014 06.07.2014 23 31 459
03.07.2014 06.07.2014 2 4 359
03.07.2014 06.07.2014 5 5 389
03.07.2014 06.07.2014 6 15 359

а нужно так
d1 d2 n1 n2 c1
30.06.2014 02.07.2014 2 15 359
30.06.2014 02.07.2014 16 22 409
30.06.2014 02.07.2014 23 31 459
03.07.2014 06.07.2014 2 4 359
03.07.2014 06.07.2014 5 5 389
03.07.2014 06.07.2014 6 15 359
03.07.2014 06.07.2014 16 22 409
03.07.2014 06.07.2014 23 31 459

т.е. чтобы в период с 30/06/2014 по 02/07/2014 попадали все значения n1 и n2 от 2 до 31, затем в период с 03/07/2014 по 06/07/2014 также попадали все значения n1 и n2 от 2 до 31 и т.д.
7 апр 14, 12:02    [15842410]     Ответить | Цитировать Сообщить модератору
 Re: Объединить последовательные диапазоны с датами  [new]
Добрый Э - Эх
Guest
Mikrosoftov,

словесная постановка задачи хромает. честно говоря, так и не понял логику построения итоговой выборки...
даже не смотря на наличие тестовых данных и желаемого результата на них...
7 апр 14, 14:12    [15843542]     Ответить | Цитировать Сообщить модератору
 Re: Объединить последовательные диапазоны с датами  [new]
Mikrosoftov
Member

Откуда:
Сообщений: 10
Добрый Э - Эх,

Есть программа. которая выгружает цены на отель на каждый день
в таком виде:

Даты заездов в отель с (d1) Даты заездов в отель по (d2) Продолжительность проживания в отеле от дней (n1) Продолжительность проживания в отеле до дней (n2) Стоимость за ночь (c1)
30.06.2014 30.06.2014 2 15 359
30.06.2014 30.06.2014 16 22 409
30.06.2014 30.06.2014 23 31 459
01.07.2014 01.07.2014 2 15 359
01.07.2014 01.07.2014 16 22 409


Цены выгружаются на каждый день как в первой таблице, а хочется выгрузить их красиво, по периодам заездов
т.е. на заезды с 30/06/14 по 02/07/14 цены на все продолжительности проживания, затем следующий период с 03/07/14 по 06/07/14 на все продолжительности и т.д.
7 апр 14, 16:53    [15845035]     Ответить | Цитировать Сообщить модератору
 Re: Объединить последовательные диапазоны с датами  [new]
Minamoto
Member

Откуда: Москва
Сообщений: 1162
Mikrosoftov, тогда у вас должна быть таблица периодов заездов, ну или логика формирования этих периодов. Поделитесь?
7 апр 14, 18:15    [15845486]     Ответить | Цитировать Сообщить модератору
 Re: Объединить последовательные диапазоны с датами  [new]
Mikrosoftov
Member

Откуда:
Сообщений: 10
Minamoto,

в начале темы таблица периодов, или я не понял вопрос?
7 апр 14, 18:56    [15845652]     Ответить | Цитировать Сообщить модератору
 Re: Объединить последовательные диапазоны с датами  [new]
HandKot
Member

Откуда: Sergiev Posad
Сообщений: 2996
Mikrosoftov, это так в тестовых данных или количество различных С1 за один день равно длительности периода к которым они относятся?
7 апр 14, 19:41    [15845804]     Ответить | Цитировать Сообщить модератору
 Re: Объединить последовательные диапазоны с датами  [new]
Minamoto
Member

Откуда: Москва
Сообщений: 1162
Mikrosoftov
Minamoto,

в начале темы таблица периодов, или я не понял вопрос?

Нет там таблицы периодов. Там только таблица по дням. Как эти дни объединять по периодам - непонятно. Вот это и нужно прояснить.
7 апр 14, 19:50    [15845842]     Ответить | Цитировать Сообщить модератору
 Re: Объединить последовательные диапазоны с датами  [new]
HandKot
Member

Откуда: Sergiev Posad
Сообщений: 2996
HandKot
Mikrosoftov, это так в тестовых данных или количество различных С1 за один день равно длительности периода к которым они относятся?

если я прав, то
select MIN(d1), MAX(d2) n1, n2, c1 from (
select d1, d2, n1, n2, c1, CHECKSUM_AGG(c1) over (partition by d1, d2) grp  from #sss1
) x
group by n1, n2, c1, grp


ЗЫЖ только надо допиливать напильником, для случаев когда у с1 есть несколько диапазонов
7 апр 14, 19:53    [15845852]     Ответить | Цитировать Сообщить модератору
 Re: Объединить последовательные диапазоны с датами  [new]
Mikrosoftov
Member

Откуда:
Сообщений: 10
HandKot,

Посмотрел по быстрому - да это как раз то что я просил, но нужно допиливать для случаев когда у с1 есть несколько диапазонов.
Постараюсь дальше сам. Если не справлюсь - попрошу о помощи.
Спасибо огромное.
7 апр 14, 23:06    [15846408]     Ответить | Цитировать Сообщить модератору
 Re: Объединить последовательные диапазоны с датами  [new]
Mikrosoftov
Member

Откуда:
Сообщений: 10
Нет, народ, дальше не двигается((
В варианте от HandKot получается много периодов внутри периодов. Пытался "напильником" - напильник сломался))
Может есть еще идеи?
10 апр 14, 03:08    [15859291]     Ответить | Цитировать Сообщить модератору
 Re: Объединить последовательные диапазоны с датами  [new]
aleks2
Guest
Mikrosoftov
Нет, народ, дальше не двигается((
В варианте от HandKot получается много периодов внутри периодов. Пытался "напильником" - напильник сломался))
Может есть еще идеи?

Дарагуля, пока ты не отфильтруешь мутный поток свово сознания, вряд ли кто-то тебе поможет.

Ибо ЭТО
Mikrosoftov
т.е. чтобы в период с 30/06/2014 по 02/07/2014 попадали все значения n1 и n2 от 2 до 31, затем в период с 03/07/2014 по 06/07/2014 также попадали все значения n1 и n2 от 2 до 31 и т.д.

понятно тока тебе.
10 апр 14, 07:42    [15859402]     Ответить | Цитировать Сообщить модератору
 Re: Объединить последовательные диапазоны с датами  [new]
HandKot
Member

Откуда: Sergiev Posad
Сообщений: 2996
aleks2
Mikrosoftov
Нет, народ, дальше не двигается((
В варианте от HandKot получается много периодов внутри периодов. Пытался "напильником" - напильник сломался))
Может есть еще идеи?

Дарагуля, пока ты не отфильтруешь мутный поток свово сознания, вряд ли кто-то тебе поможет.

Ибо ЭТО
Mikrosoftov
т.е. чтобы в период с 30/06/2014 по 02/07/2014 попадали все значения n1 и n2 от 2 до 31, затем в период с 03/07/2014 по 06/07/2014 также попадали все значения n1 и n2 от 2 до 31 и т.д.

понятно тока тебе.

поддерживаю.
Приведите тестовые данные и по шажкам, почему и только так такая-то запись должна попасть в такой-то период
10 апр 14, 08:09    [15859434]     Ответить | Цитировать Сообщить модератору
 Re: Объединить последовательные диапазоны с датами  [new]
Mikrosoftov
Member

Откуда:
Сообщений: 10
попытаюсь объяснить что мне нужно:
есть программа которая выгружает цены на отель в виде таблицы
т.е. на каждый день заезда, от 2-х дней до 31 дней.
Цены отличаются в зависимости от количества проживаемых дней.
Т.о. в один и тот же период заездов не может быть разного разбиения продолжительности в днях, напр. на заезд 01/07/14 цена дается на проживание от 2-х до 15-ти дней, от 16-ти до 22-х и от 23-х до месяца см. таблицы во вложении
Цена, соответственно разная на разные продолжительности.
В таком виде как выгружает программа - каталог становиться нечетабельным т.к. очень много записей и я пытаюсь выгрузить его красиво, объединив одинаковые цены с разбиением по периодам, т.к. часто на какой-то период действует одна цена.

ПРИКРЕПЛЯЮ ФАЙЛ .EXL, в котором описываю как могу подробно что мне нужно, с таблицами для наглядности. А также недостатки решений от alex2, HandKot и Mikrosoftov.
ниже таблица для тестирования и варианты решений от alex2, HandKot и Mikrosoftov

--- ТАБЛИЦА
declare @sss1 table  (id int identity, d1 date, d2 date, n1 int, n2 int, c1 int)
insert into @sss1 (d1, d2, c1, n1, n2) values
('2014-07-01', '2014-07-01', 100, 2, 15),
('2014-07-01', '2014-07-01', 200, 16, 22),
('2014-07-01', '2014-07-01', 300, 23, 31),
('2014-07-02', '2014-07-02', 100, 2, 15),
('2014-07-02', '2014-07-02', 200, 16, 22),
('2014-07-02', '2014-07-02', 300, 23, 31),
('2014-07-03', '2014-07-03', 150, 2, 15),
('2014-07-03', '2014-07-03', 200, 16, 22),
('2014-07-03', '2014-07-03', 300, 23, 31),
('2014-07-04', '2014-07-04', 150, 2, 15),
('2014-07-04', '2014-07-04', 200, 16, 22),
('2014-07-04', '2014-07-04', 300, 23, 31),
('2014-07-05', '2014-07-05', 100, 2, 4),
('2014-07-05', '2014-07-05', 150, 5, 5),
('2014-07-05', '2014-07-05', 100, 6, 15),
('2014-07-05', '2014-07-05', 200, 16, 22),
('2014-07-05', '2014-07-05', 300, 23, 31),
('2014-07-06', '2014-07-06', 100, 2, 4),
('2014-07-06', '2014-07-06', 150, 5, 5),
('2014-07-06', '2014-07-06', 100, 6, 15),
('2014-07-06', '2014-07-06', 200, 16, 22),
('2014-07-06', '2014-07-06', 300, 23, 31),
('2014-07-07', '2014-07-07', 100, 2, 15),
('2014-07-07', '2014-07-07', 200, 16, 22),
('2014-07-07', '2014-07-07', 300, 23, 31),
('2014-07-08', '2014-07-08', 120, 2, 15),
('2014-07-08', '2014-07-08', 220, 16, 22),
('2014-07-08', '2014-07-08', 320, 23, 31),
('2014-07-09', '2014-07-09', 120, 2, 15),
('2014-07-09', '2014-07-09', 220, 16, 22),
('2014-07-09', '2014-07-09', 320, 23, 31),
('2014-07-10', '2014-07-10', 120, 2, 15),
('2014-07-10', '2014-07-10', 220, 16, 22),
('2014-07-10', '2014-07-10', 320, 23, 31),
('2014-07-11', '2014-07-11', 100, 2, 15),
('2014-07-11', '2014-07-11', 200, 16, 22),
('2014-07-11', '2014-07-11', 300, 23, 31),
('2014-07-12', '2014-07-12', 100, 2, 15),
('2014-07-12', '2014-07-12', 200, 16, 22),
('2014-07-12', '2014-07-12', 300, 23, 31),
('2014-07-13', '2014-07-13', 100, 2, 15),
('2014-07-13', '2014-07-13', 200, 16, 22),
('2014-07-13', '2014-07-13', 300, 23, 31),
('2014-07-14', '2014-07-14', 120, 2, 15),
('2014-07-14', '2014-07-14', 220, 16, 22),
('2014-07-14', '2014-07-14', 320, 23, 31),
('2014-07-15', '2014-07-15', 100, 2, 15),
('2014-07-15', '2014-07-15', 200, 16, 22),
('2014-07-15', '2014-07-15', 300, 23, 31)

select * from @sss1 order by d1, n1
















------------------------------------------------------------------
----1. РЕШЕНИЕ ОТ alex2
--------------------------------------------------------------------
declare @b table (id int, d1 date, d2 date, n1 int, n2 int, c1 int, n int identity primary key clustered);

insert @b
  select t.id, t.d1, t.d2, t.n1, t.n2, t.c1
    from @sss1 t left outer join @sss1 tt on t.n1 = tt.n1 and t.n2 = tt.n2 and t.c1 = tt.c1 and t.id <> tt.id and t.d1 = dateadd(day, 1, tt.d2)
    where tt.id is null
    order by t.d1, t.d2, t.c1, t.n1 ASC;
    
--select * from @b

declare @e table (id int, d1 date, d2 date, n1 int, n2 int, c1 int, n int identity primary key clustered);
insert @e
  select t.id, t.d1, t.d2, t.n1, t.n2, t.c1 
    from @sss1 t left outer join @sss1 tt on t.n1 = tt.n1 and t.n2 = tt.n2 and t.c1 = tt.c1 and t.id <> tt.id and t.d2 = dateadd(day, -1, tt.d1)
    where tt.id is null
    order by t.d1, t.d2, t.c1, t.n1 ASC;
    
--select * from @e
declare @t table (id int identity, d1 Date, d2 Date, n1 int, n2 int, c1 int)
insert into @t (d1, d2, n1, n2, c1) 

select b.d1, e.d2, b.n1, b.n2, b.c1
  from @b b inner join @e e on b.n = e.n ORDER BY b.d1, b.n1

select * from @t ORDER BY d1, n1
--------------------------------------------------------------------


--------------------------------------------------------------------
----2. РЕШЕНИЕ ОТ HandKot
--------------------------------------------------------------------
declare @t table  (d1 date, d2 date, n1 int, n2 int, c1 int)
insert into @t (d1, d2, n1, n2, c1)

select MIN(d1), MAX(d2), n1, n2, c1 from (
select d1, d2, n1, n2, c1, CHECKSUM_AGG(c1) over (partition by d1, d2) grp  from @sss1
) x
group by n1, n2, c1, grp 
select * from  @t
ORDER BY d1,n1
------------------------------------------------------------------

--------------------------------------------------------------------
----3. РЕШЕНИЕ ОТ Mikrosoftov
--------------------------------------------------------------------
declare @t1 table (d1 Date, d2 Date, n1 int, n2 int, c1 int)
insert into @t1 (n1, n2, c1, d1, d2) 

SELECT
	T.n1,
	T.n2,
	T.c1,
T.d1,
 (
  SELECT MIN(TT.d2)
  FROM @sss1 TT
  WHERE TT.c1=T.c1 AND TT.d1>=T.d1
  AND NOT EXISTS(SELECT * FROM @sss1 TTT WHERE TTT.c1=TT.c1 AND
  TTT.n1=TT.n1 AND 
  TTT.n2=TT.n2 AND
  --TTT.n1=TT.n2+1 AND
  TTT.d1=dateadd(day,+1,cast(substring(convert(nvarchar(100), TT.d2, 120),1,10) as datetime)))
 ) d2
FROM @sss1 T
WHERE NOT EXISTS(SELECT * FROM @sss1 TT WHERE TT.c1=T.c1 AND
TT.n1=T.n1 AND
TT.n2=T.n2 AND
--TT.n2=T.n1-1 AND
TT.d2=dateadd(day,-1,cast(substring(convert(nvarchar(100), T.d1, 120),1,10) as datetime)))

SELECT * FROM @t1 ORDER BY d1, n1


К сообщению приложен файл (ДЛЯ САЙТА.xls - 40Kb) cкачать
11 апр 14, 04:33    [15865701]     Ответить | Цитировать Сообщить модератору
 Re: Объединить последовательные диапазоны с датами  [new]
aleks2
Guest
1. Основная причина всех заморочек программистов - неспособность ВНЯТНО объяснить СЕБЕ и другим чего ему надо.

2. Героическим напряжением интеллекта я вангую... но получается надвое (хрустальный шар мутноват)

Вариант 1:
Тредстартеру надо
объединить непрерывные периоды d1-d2 для одинаковых n1, n2, c1
и затем
объединить непрерывные периоды n1-n2 для одинаковых d1, d2, c1

Вариант 2:
Тредстартеру надо
объединить непрерывные периоды n1-n2 для одинаковых d1, d2, c1
и затем
объединить непрерывные периоды d1-d2 для одинаковых n1,n2,c1

ПРИМЕЧАНИЕ: "непрерывными" считаются периоды x1-x2 и y1-y2, если x2 + 1 = y1.

Оба варианта решаются так, как уже было десять раз показано.
11 апр 14, 05:55    [15865711]     Ответить | Цитировать Сообщить модератору
 Re: Объединить последовательные диапазоны с датами  [new]
HandKot
Member

Откуда: Sergiev Posad
Сообщений: 2996
Mikrosoftov
Нет, народ, дальше не двигается((
В варианте от HandKot получается много периодов внутри периодов. Пытался "напильником" - напильник сломался))
Может есть еще идеи?

не тот напильник брали, или не той стороной работали :)
как и сказал
aleks2
Оба варианта решаются так, как уже было десять раз показано.

+
--схлопывание я бы сделал по способу "инвариант группы", но отдаю должное aleks2 
--на другом наборе данных результат может быть неправильным
-- все из-за функции CHECKSUM_AGG
-- возможно сделано много лишних движений, если есть желание, то вперед на усовершенствоание
--- ТАБЛИЦА
declare @sss1 table  (id int identity, d1 date, d2 date, n1 int, n2 int, c1 int)
insert into @sss1 (d1, d2, c1, n1, n2) values
('2014-07-01', '2014-07-01', 100, 2, 15),
('2014-07-01', '2014-07-01', 200, 16, 22),
('2014-07-01', '2014-07-01', 300, 23, 31),
('2014-07-02', '2014-07-02', 100, 2, 15),
('2014-07-02', '2014-07-02', 200, 16, 22),
('2014-07-02', '2014-07-02', 300, 23, 31),
('2014-07-03', '2014-07-03', 150, 2, 15),
('2014-07-03', '2014-07-03', 200, 16, 22),
('2014-07-03', '2014-07-03', 300, 23, 31),
('2014-07-04', '2014-07-04', 150, 2, 15),
('2014-07-04', '2014-07-04', 200, 16, 22),
('2014-07-04', '2014-07-04', 300, 23, 31),
('2014-07-05', '2014-07-05', 100, 2, 4),
('2014-07-05', '2014-07-05', 150, 5, 5),
('2014-07-05', '2014-07-05', 100, 6, 15),
('2014-07-05', '2014-07-05', 200, 16, 22),
('2014-07-05', '2014-07-05', 300, 23, 31),
('2014-07-06', '2014-07-06', 100, 2, 4),
('2014-07-06', '2014-07-06', 150, 5, 5),
('2014-07-06', '2014-07-06', 100, 6, 15),
('2014-07-06', '2014-07-06', 200, 16, 22),
('2014-07-06', '2014-07-06', 300, 23, 31),
('2014-07-07', '2014-07-07', 100, 2, 15),
('2014-07-07', '2014-07-07', 200, 16, 22),
('2014-07-07', '2014-07-07', 300, 23, 31),
('2014-07-08', '2014-07-08', 120, 2, 15),
('2014-07-08', '2014-07-08', 220, 16, 22),
('2014-07-08', '2014-07-08', 320, 23, 31),
('2014-07-09', '2014-07-09', 120, 2, 15),
('2014-07-09', '2014-07-09', 220, 16, 22),
('2014-07-09', '2014-07-09', 320, 23, 31),
('2014-07-10', '2014-07-10', 120, 2, 15),
('2014-07-10', '2014-07-10', 220, 16, 22),
('2014-07-10', '2014-07-10', 320, 23, 31),
('2014-07-11', '2014-07-11', 100, 2, 15),
('2014-07-11', '2014-07-11', 200, 16, 22),
('2014-07-11', '2014-07-11', 300, 23, 31),
('2014-07-12', '2014-07-12', 100, 2, 15),
('2014-07-12', '2014-07-12', 200, 16, 22),
('2014-07-12', '2014-07-12', 300, 23, 31),
('2014-07-13', '2014-07-13', 100, 2, 15),
('2014-07-13', '2014-07-13', 200, 16, 22),
('2014-07-13', '2014-07-13', 300, 23, 31),
('2014-07-14', '2014-07-14', 120, 2, 15),
('2014-07-14', '2014-07-14', 220, 16, 22),
('2014-07-14', '2014-07-14', 320, 23, 31),
('2014-07-15', '2014-07-15', 100, 2, 15),
('2014-07-15', '2014-07-15', 200, 16, 22),
('2014-07-15', '2014-07-15', 300, 23, 31)

declare @p table  (id int identity, d1 date, d2 date, n1 int, n2 int, c1 int, grp bigint)
insert into @p (d1, d2, n1, n2, c1, grp)
select d1, d2, n1, n2, c1, CHECKSUM_AGG(n1+n2+c1) over (partition by d1, d2) grp  from @sss1

select * from @p

declare @b table (id int, d1 date, d2 date, n1 int, n2 int, c1 int, grp bigint, n int identity primary key clustered);
declare @e table (id int, d1 date, d2 date, n1 int, n2 int, c1 int, grp bigint, n int identity primary key clustered);


insert @b(id, d1, d2, n1, n2, c1, grp)
  select t.id, t.d1, t.d2, t.n1, t.n2, t.c1, t.grp
    from @p t left outer join @p tt on t.grp = tt.grp and t.id <> tt.id and t.d1 = dateadd(day, 1, tt.d2)
    where tt.id is null
    order by t.d1, t.d2, t.c1, t.n1 ASC;
    
--select * from @b

insert @e(id, d1, d2, n1, n2, c1, grp)
  select t.id, t.d1, t.d2, t.n1, t.n2, t.c1, t.c1 
    from @p t left outer join @p tt on t.grp = tt.grp and t.id <> tt.id and t.d2 = dateadd(day, -1, tt.d1)
    where tt.id is null
    order by t.d1, t.d2, t.c1, t.n1 ASC;
    
--select * from @e
declare @t table (id int identity, d1 Date, d2 Date, n1 int, n2 int, c1 int)
insert into @t (d1, d2, n1, n2, c1) 

select b.d1, e.d2, b.n1, b.n2, b.c1
  from @b b inner join @e e on b.n = e.n ORDER BY b.d1, b.n1

select * from @t ORDER BY d1, n1
11 апр 14, 09:23    [15866028]     Ответить | Цитировать Сообщить модератору
 Re: Объединить последовательные диапазоны с датами  [new]
Mikrosoftov
Member

Откуда:
Сообщений: 10
HandKot,
Супер, спасибо огромное, это именно то, что я искал.
в скрипте есть небольшая опечатка
здесь
insert @e(id, d1, d2, n1, n2, c1, grp)
  select t.id, t.d1, t.d2, t.n1, t.n2, t.c1, t.c1 

должно быть так
insert @e(id, d1, d2, n1, n2, c1, grp)
  select t.id, t.d1, t.d2, t.n1, t.n2, t.c1, t.grp 

Всем огромное спасибо за помощь
11 апр 14, 15:16    [15868630]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить