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

Откуда:
Сообщений: 120
Подскажите как реализовать на 2000 sql обьединение пересекающихся интервалов, посмотрел по форуму ничего хорошего не нашел.
как пример есть 3 интервала 1-15, 15-20, 20-22, обьеденить первый со 2 и 2 с 3 у меня получается, а как сделать так чтобы обьеденить в один интервал не понятно.
https://www.sql.ru/forum/actualthread.aspx?tid=576070 тут как раз то что надо но там запрос только для 2005. есть ли решение для 2000?
20 ноя 08, 17:51    [6468225]     Ответить | Цитировать Сообщить модератору
 Re: пересекающиеся интервалы  [new]
.+-
Guest
Lurd
но там запрос только для 2005. есть ли решение для 2000?
Добрый Э - Эх
WITH там по сути - эмуляция данных твоей таблицы... Оно там просто для того,чтобы было видно, какая по структуре таблица была использована мною и какие данные из неё участвовали в построении запроса...
20 ноя 08, 17:58    [6468278]     Ответить | Цитировать Сообщить модератору
 Re: пересекающиеся интервалы  [new]
Lurd
Member

Откуда:
Сообщений: 120
ну там не совсем на обьединение интервалов. мне то нужно именно в селекте получить из 3х интервалов 1 и все
21 ноя 08, 10:26    [6469983]     Ответить | Цитировать Сообщить модератору
 Re: пересекающиеся интервалы  [new]
.+-
Guest
Lurd
тут как раз то что надо
Lurd
ну там не совсем на обьединение интервалов
21 ноя 08, 10:36    [6470077]     Ответить | Цитировать Сообщить модератору
 Re: пересекающиеся интервалы  [new]
.+-
Guest
Lurd
мне то нужно именно в селекте получить из 3х интервалов 1 и все
with t as (
select 1 as id, 1 as f1, 15 as f2 union all
select 2 as id, 15 as f1, 20 as f2 union all
select 3 as id, 20 as f1, 22 as f2
)

select min(f1) as f1, max(f2) as f2, min(id) as min_id, max(id) as max_id
  from (
         select t0.*,
                (
                  select count(case when t2.id is null then 1 end )
                    from t t1
                    left join t t2
                      on t1.id - 1 = t2.id
                     and t1.f1 = t2.f2
                     where t1.id <= t0.id
                ) as grp_id
           from t t0
       ) v         
 group by grp_id
результат
f1          f2          min_id      max_id
----------- ----------- ----------- -----------
1           22          1           3
Решение взято отсюда же
21 ноя 08, 10:43    [6470144]     Ответить | Цитировать Сообщить модератору
 Re: пересекающиеся интервалы  [new]
Добрый Э - Эх
Guest
Lurd
ну там не совсем на обьединение интервалов. мне то нужно именно в селекте получить из 3х интервалов 1 и все

Пусть есть таблица T, в которой содержатся следующие данные:
select * from t
f1f2
115
1520
2022
3135
3540
4052
5260
6570
7089
8993

Как легко заметить - в таблице есть три непрерывных интервала, каждый из которых записан несколькими строками

Вот запрос, который собирает последовательные интервалы в один интервал:
select min(f1) as f1, max(f2) as f2, count(1) as cnt
  from (
         select t0.*,
                (
                  select count(case when t2.f1 is null then 1 end )
                    from t t1
                    left join t t2
                      on t1.f1 = t2.f2
                   where t1.f1 <= t0.f1
                ) as grp_id
           from t t0
       ) v         
 group by grp_id


Query finished, retrieving results...

F1   F2   CNT
--   --   ---
 1   22     3 
31   60     4 
65   93     3 

3 row(s) retrieved

З.Ы.
Решение расчитано на то, что ни исходные, ни "агрегированные" интервалы не пересекаются. Если есть пересечение интервалов, то решение будет немного другим...
21 ноя 08, 11:12    [6470408]     Ответить | Цитировать Сообщить модератору
 Re: пересекающиеся интервалы  [new]
Добрый Э - Эх
Guest
Если каждый "агрегированный" интервал состоит из пересекающихся подинтервалов, то есть данные в таблице имеют следующий вид:
select * from t;
f1f2
115
1521
1922
3137
3543
4054
5260
6578
7092
8995

То собрать такие подинтервалы можно запросом:
select f1 as [Начало непрерывного интервала],
       min(f2) as [Конец непрерывного интервала]
  from 
       (
          select f1
            from t s1
           where not exists (
                               select null
                                 from t s2
                                where s2.f1 < s1.f1
                                  and s2.f2 >= s1.f1
                            )
       ) v_begin,
       (
          select f2
            from t s1
           where not exists (
                               select null
                                 from t s2
                                where s2.f2 > s1.f2
                                  and s2.f1 <= s1.f2
                            )
       ) v_end
 where f1 <= f2
  group by f1

Query finished, retrieving results...

Начало непрерывного интервала   Конец непрерывного интервала
-----------------------------   ----------------------------
                            1                             22
                           31                             60
                           65                             95

3 row(s) retrieved
21 ноя 08, 12:24    [6470986]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: пересекающиеся интервалы  [new]
гость123456789
Guest
Добрый Э - Эх,

Знаю что прошло сто лет, но все равно большое человеческое спасибо! :)
3 май 11, 21:20    [10600756]     Ответить | Цитировать Сообщить модератору
 Re: пересекающиеся интервалы  [new]
a569406
Guest
Вопрос к знатокам, в последнем сообщении, Добрый Э - Эх, предложил решение поиска интервалов и оно замечательно работает, и теперь вопрос с усложнением задачи, у меня есть счетчики (интервал с, по (f1, f2)) и стоимости (интервал с, по (t1, t2)), нужно сгруппировать их по id b по двум интервалам f1, f2 и t1, t2

данные:
id- f1 f2 t1 t2
1- 5 10 100 200
2- 7 15 300 400
3- 20 25 350 600
4- 1 3 700 750
5- 10 13 710 780


нужно получить такой результат:
id(id1;id2...idx)- f1 f2 t1 t2
1;2;3- 5 25 100 600
4;5- 1 13 700 780


Надеюсь условие понятно, если нет - уточню... Если получится найти решение, то рабочий отчет будет работать на порядок быстрее. :)

Заранее спасибо!
4 май 11, 14:30    [10604002]     Ответить | Цитировать Сообщить модератору
 Re: пересекающиеся интервалы  [new]
aleks2
Guest
1. Ты просто нашел на форуме самое тормознутое решение. Два коррелированных подзапроса да ишо и группировка - это ишо та ракета...
2. Поищи получше.
4 май 11, 14:36    [10604048]     Ответить | Цитировать Сообщить модератору
 Re: пересекающиеся интервалы  [new]
Начинающий SQL 2008
Member

Откуда:
Сообщений: 438
Надеюсь условие понятно, если нет - уточню
Сортируем по id, далее двигаемся по полю f1, как только значение меньше предыдущего, то это начало нового интервала? Так?
4 май 11, 15:29    [10604429]     Ответить | Цитировать Сообщить модератору
 Re: пересекающиеся интервалы  [new]
a569406
Guest
Начинающий SQL 2008,

нет, группируем все что связано пересечениями, т.е. если f1, f2 и t1, t2. К примеру:

id - f1 f2 t1 t2
1 - 5 10 100 200
2 - 15 20 150 225
3 - 5 25 100 200
4 - 1 3 250 500
5 - 30 35 710 780


в таблице красным подсветил первую связку со вторым, зеленым - одну из связок первого со вторым

первый и второй связаны по t,
второй и третий по f и по t (так как диапазоны пересекаются и в f и в t)
третий и четвертый не связаны, т.к. из четвертого не пересекаются диапазоны ни с одним из диапазонов с которыми пересекается 3й и с самим третьим.
четвертый и пятый не связанны по той же причине что и четвертый с третьим

нужно получить такой результат:

id(id1;id2...idx) - f1 f2 t1 t2
1;2;3 - 5 25 100 400
4 - 1 3 250 500
5 - 30 35 710 780


если надо, еще отвечу на вопросы по условию
4 май 11, 16:37    [10605199]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить