powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Пятничная задача: Красное и черное
25 сообщений из 176, страница 1 из 8
Пятничная задача: Красное и черное
    #40017941
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Это очередная вариация на тему интервалов. Мне подобное на форуме не попадалось, но сорри если баян.

Есть интервалы двух цветов и требуется получить результирующую разбивку как показано ниже.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
with t (x1, x2, c) as
(
select 1, 4, 'red' from dual
union all select 7, 10, 'red' from dual
union all select 13, 16, 'red' from dual
union all select 3, 14, 'black' from dual
union all select 16, 19, 'black' from dual
union all select 18, 22, 'red' from dual
union all select 22, 25, 'black' from dual
union all select 26, 28, 'red' from dual
union all select 29, 30, 'black' from dual
union all select 32, 33, 'black' from dual
)
select ...
/

        X1         X2 RESULT
---------- ---------- -------
         1          2 red
         3          4 overlap
         5          6 black
         7         10 overlap
        11         12 black
        13         14 overlap
        15         15 red
        16         16 overlap
        17         17 black
        18         19 overlap
        20         21 red
        22         22 overlap
        23         25 black
        26         28 red
        29         30 black
        31         31 none
        32         33 black

17 rows selected.

Входные интервалы каждого отдельного цвета не пересекаются и не соприкасаются.

Картинка вероятно нагляднее покажет как получен результат.
...
Рейтинг: 0 / 0
Пятничная задача: Красное и черное
    #40017949
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кобанчег,

Верхняя и нижняя граница всегда определены имеющимися интервалами?
...
Рейтинг: 0 / 0
Пятничная задача: Красное и черное
    #40017961
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
env,

Не совсем понял вопрос. На выходе должен быть диапазон от начала первого до конца последнего.
...
Рейтинг: 0 / 0
Пятничная задача: Красное и черное
    #40017971
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кобанчег,

Напрашивается решение через непрерывный список от min до max и start of group, но это видимо слишком простое и очевидное.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
with t (x1, x2, c) as
(
select 1, 4, 'red' from dual
union all select 7, 10, 'red' from dual
union all select 13, 16, 'red' from dual
union all select 3, 14, 'black' from dual
union all select 16, 19, 'black' from dual
union all select 18, 22, 'red' from dual
union all select 22, 25, 'black' from dual
union all select 26, 28, 'red' from dual
union all select 29, 30, 'black' from dual
union all select 32, 33, 'black' from dual
),
minmax as (
    select
        min(x1)     mn,
        max(x2)     mx
    from
        t
), 
nums as (
    select
        mn + level - 1 n
    from
        minmax
    connect by
        level <= mx - mn + 1
), 
vect as (
    select
        n,
        decode(count(distinct t.c), 1, max(c), 0, 'none', 'overlap') c
    from
        nums,
        t
    where
        nums.n between t.x1 (+) and t.x2 (+)
    group by
        nums.n
), 
sog as (
    select
        n,
        c,
        decode(c, lag(c, 1, c) over(order by n), 0, 1) g
    from
        vect
), 
grp as (
    select
        n,
        c,
        sum(g) over(order by n) gr
    from
        sog
)
select
    min(n),
    max(n),
    max(c)
from
    grp
group by
    gr
order by
    gr;

    MIN(N)     MAX(N) MAX(C)
---------- ---------- -------
         1          2 red
         3          4 overlap
         5          6 black
         7         10 overlap
        11         12 black
        13         14 overlap
        15         15 red
        16         16 overlap
        17         17 black
        18         19 overlap
        20         21 red
        22         22 overlap
        23         25 black
        26         28 red
        29         30 black
        31         31 none
        32         33 black

...
Рейтинг: 0 / 0
Пятничная задача: Красное и черное
    #40017975
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кобанчег,

red =1
black=2
суммируем с перекрытием
3-overlap
0-прозрачный


.....
stax
...
Рейтинг: 0 / 0
Пятничная задача: Красное и черное
    #40017977
Вячеслав Любомудров
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
model + overlap ?
...
Рейтинг: 0 / 0
Пятничная задача: Красное и черное
    #40017981
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кобанчег
если баян
join с подинтервальчиками .
...
Рейтинг: 0 / 0
Пятничная задача: Красное и черное
    #40017982
Вячеслав Любомудров
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кстати, насколько помню была какая-то не[полностью]документированная функция типа именно overlap для работы с датами и числами
Или только датами/диапазонами(?)
...
Рейтинг: 0 / 0
Пятничная задача: Красное и черное
    #40017988
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
Кобанчег,

red =1
black=2
суммируем с перекрытием
3-overlap
0-прозрачный


зі
нашел
https://www.sql.ru/forum/1297132/razdelit-na-neperesekaushhiesya-intervaly-dat-otrezki-s-ssumirovaniem-summy-v-peresecheniyah

.....
stax
...
Рейтинг: 0 / 0
Пятничная задача: Красное и черное
    #40017996
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
env
Кобанчег,

Напрашивается решение через непрерывный список от min до max и start of group, но это видимо слишком простое и очевидное.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
with t (x1, x2, c) as
(
select 1, 4, 'red' from dual
union all select 7, 10, 'red' from dual
union all select 13, 16, 'red' from dual
union all select 3, 14, 'black' from dual
union all select 16, 19, 'black' from dual
union all select 18, 22, 'red' from dual
union all select 22, 25, 'black' from dual
union all select 26, 28, 'red' from dual
union all select 29, 30, 'black' from dual
union all select 32, 33, 'black' from dual
),
minmax as (
    select
        min(x1)     mn,
        max(x2)     mx
    from
        t
), 
nums as (
    select
        mn + level - 1 n
    from
        minmax
    connect by
        level <= mx - mn + 1
), 
vect as (
    select
        n,
        decode(count(distinct t.c), 1, max(c), 0, 'none', 'overlap') c
    from
        nums,
        t
    where
        nums.n between t.x1 (+) and t.x2 (+)
    group by
        nums.n
), 
sog as (
    select
        n,
        c,
        decode(c, lag(c, 1, c) over(order by n), 0, 1) g
    from
        vect
), 
grp as (
    select
        n,
        c,
        sum(g) over(order by n) gr
    from
        sog
)
select
    min(n),
    max(n),
    max(c)
from
    grp
group by
    gr
order by
    gr;

    MIN(N)     MAX(N) MAX(C)
---------- ---------- -------
         1          2 red
         3          4 overlap
         5          6 black
         7         10 overlap
        11         12 black
        13         14 overlap
        15         15 red
        16         16 overlap
        17         17 black
        18         19 overlap
        20         21 red
        22         22 overlap
        23         25 black
        26         28 red
        29         30 black
        31         31 none
        32         33 black

Да, это весьма неэффективно и завязано на натуральные числа.
Интервалы могут быть произвольной длины и не обязательно с целыми границами.
...
Рейтинг: 0 / 0
Пятничная задача: Красное и черное
    #40018000
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
Stax
Кобанчег,

red =1
black=2
суммируем с перекрытием
3-overlap
0-прозрачный


зі
нашел
https://www.sql.ru/forum/1297132/razdelit-na-neperesekaushhiesya-intervaly-dat-otrezki-s-ssumirovaniem-summy-v-peresecheniyah

.....
stax
Идея понятна, но можно без джойнов и подзапросов.
...
Рейтинг: 0 / 0
Пятничная задача: Красное и черное
    #40018003
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Elic
Кобанчег
если баян
join с подинтервальчиками .
Наиболее эффективно без джойнов.
Но некоторая баянистость просматривается, да.
...
Рейтинг: 0 / 0
Пятничная задача: Красное и черное
    #40018009
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вячеслав Любомудров
model + overlap ?
В тяжелой артиллерии нет особой необходимости.
Вячеслав Любомудров
Кстати, насколько помню была какая-то не[полностью]документированная функция типа именно overlap для работы с датами и числами
Или только датами/диапазонами(?)
overlap s

Но недокументированное это неспортивно (и для данной задачи нет надобности).
...
Рейтинг: 0 / 0
Пятничная задача: Красное и черное
    #40018016
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кобанчег

Наиболее эффективно без джойнов.
Но некоторая баянистость просматривается, да.


unpivot можно?

для
union all select 7, 10, 'red' from dual
union all select 10, 14, 'black' from dual

10 10 overlap?

.....
stax
...
Рейтинг: 0 / 0
Пятничная задача: Красное и черное
    #40018018
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
unpivot можно?
Да всё что угодно можно.
Stax
10 10 overlap?
Да.

PS. На самом деле мне стоило состряпать более адекватный пример с real numbers
(тогда бы 10 10 было касание а не перекрытие на единицу) но уже есть как есть.
...
Рейтинг: 0 / 0
Пятничная задача: Красное и черное
    #40018022
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кобанчег
завязано на натуральные числа
Должен признать что моя постановка именно это и подразумевает, но всё равно генерить диапазоны connect by - не самый удачный вариант.
...
Рейтинг: 0 / 0
Пятничная задача: Красное и черное
    #40018271
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кобанчег,

была идейка red full outer join black on пересекаются
но плюнул перебирать случаи пересечений
.....
stax
...
Рейтинг: 0 / 0
Пятничная задача: Красное и черное
    #40018281
graycode
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Stax
Кобанчег,

red =1
black=2
суммируем с перекрытием
3-overlap
0-прозрачный


.....
stax

Суммировать хорошая идея, правда как без трансформации запроса это делать я не знаю.

Вижу примерно следующий алгоритм, x1 и x2 в один столбец, каждый признак (red, black) отдельным столбцом, для начала периода (x1) признаку +1, там где кончается период (x2) признаку -1, если накопительная сумма с учетом периода больше нуля значит признак в периоде (в вертикальном виде, период это две ближайшие строки) включен, если нет значит выключен, потом преобразовать обратно в периоды.

PS: реализовывать лень)))
...
Рейтинг: 0 / 0
Пятничная задача: Красное и черное
    #40018325
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
Кобанчег,

была идейка red full outer join black on пересекаются
но плюнул перебирать случаи пересечений
.....
stax
Да, при том подходе надо скурпулёзно все перебирать и солжно для понимания и поддержки имхо.

Более просто и эффективно развернуть все отрезки в один ряд (cross join/pivot) и определить что есть что в результате (аналитика/pattern matching).

В общем мое решение выглядит так
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
select x1, x2, result
from t unpivot (x for type in (x1, x2))
match_recognize
(
  order by x, type
  measures
    case when type = 'X2' and next(type) = 'X1' and next(x) - x =1 then 1 end touch,
    case when next(x) = x and next(type) = type then 1 end same_bound,
    x + decode(type, 'X2', 1, 0) x1,
    next(x) - decode(next(type), 'X1', 1, 0) x2,
    decode(sum(decode(c, 'red', 1, 'black', 2) * decode(type, 'X1', 1, 'X2', -1)),
           1, 'red', 2, 'black', 3, 'overlap', 'none') result    
  all rows per match
  pattern (x+)
  define x as next(x) is not null
)
where touch is null and same_bound is null



touch используется для фильтра когда конец одного соприкасается с началом другого,
а same_bound для исключения из результата первой из точек когда начала либо концы совпадают.
...
Рейтинг: 0 / 0
Пятничная задача: Красное и черное
    #40018328
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В общем эта была разминка, теперь предлагается задачка посложнее.

Необходимо наложить интервалы из источника на приемник с приоритетом из источника (если есть пересечение).

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
with t (x1, x2, c, flag) as
(
select 1, 4, 'red', 'src' from dual
union all select 7, 10, 'yellow', 'src' from dual
union all select 13, 16, 'red', 'src' from dual
--union all select 3, 14, 'black' from dual
union all select 3, 7, 'black', 'tgt' from dual
union all select 9, 11, 'black', 'tgt' from dual
union all select 13, 14, 'black', 'tgt' from dual
--
union all select 16, 19, 'blue', 'tgt' from dual
union all select 18, 22, 'green', 'src' from dual
union all select 22, 25, 'black', 'tgt' from dual
union all select 26, 28, 'red', 'src' from dual
union all select 29, 30, 'red', 'tgt' from dual
union all select 32, 33, 'black', 'tgt' from dual
)
select ...
/

        X1         X2 RESULT
---------- ---------- ------
         1          4 red
         5          6 black
         7         10 yellow
        11         11 black
        12         12
        13         16 red
        17         17 blue
        18         22 green
        23         25 black
        26         30 red
        31         31
        32         33 black

12 rows selected.

Здесь не удастся выкрутиться с decode + sum ибо цветов потенциально неограниченное множество.

И снова картинка для наглядности.
...
Рейтинг: 0 / 0
Пятничная задача: Красное и черное
    #40018332
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
graycode

PS: реализовывать лень)))


https://www.sql.ru/forum/1297132/razdelit-na-neperesekaushhiesya-intervaly-dat-otrezki-s-ssumirovaniem-summy-v-peresecheniyah

ета задачка даж проще, токо одно пересечение

.....
stax
...
Рейтинг: 0 / 0
Пятничная задача: Красное и черное
    #40018367
graycode
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
del
...
Рейтинг: 0 / 0
Пятничная задача: Красное и черное
    #40018404
graycode
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Кобанчег
В общем мое решение выглядит так

Это называется без тяжелой артиллерии?

Я думал без тяжелой артиллерии выглядит примерно так:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
with t (x1, x2, c) as
(
select 1, 4, 'red' from dual
union all select 7, 10, 'red' from dual
union all select 13, 16, 'red' from dual
union all select 3, 14, 'black' from dual
union all select 16, 19, 'black' from dual
union all select 18, 22, 'red' from dual
union all select 22, 25, 'black' from dual
union all select 26, 28, 'red' from dual
union all select 29, 30, 'black' from dual
union all select 32, 33, 'black' from dual
)
, t1 (x, red, black) as
(
select x1 as x, decode(c, 'red', 1, 0), decode(c, 'black', 1, 0) from t
union all
select x2 + 1 as x, decode(c, 'red', -1, 0), decode(c, 'black', -1, 0) from t
)
, t2 (x, red, black) as
(
select distinct x
     , sum(red) over (order by x range unbounded preceding)
     , sum(black) over (order by x range unbounded preceding)
  from t1
)
, t3 (x1, x2, c) as
(
select x
     , lead(x) over (order by x) - 1
     , case when red > 0 and black > 0 then 'overlap'
            when red > 0 then 'red'
            when black > 0 then 'black'
            else 'none' end
  from t2
)
select * from t3 where x2 is not null order by x1
...
Рейтинг: 0 / 0
Пятничная задача: Красное и черное
    #40018406
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Одно из решений.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
p(r,clr,cln) as
(
select 0, null, null from dual union all
select r+1,
       nvl((select max(c) from t where flag='src' and r+1 between x1 and x2),
           (select max(c) from t where flag='tgt' and r+1 between x1 and x2)),
       nvl((select max(c) from t where flag='src' and r+2 between x1 and x2),
           (select max(c) from t where flag='tgt' and r+2 between x1 and x2))
  from p where r < (select max(x2) from t)
)
select nvl(lag(r) over (order by r),1) as y1,
       r as y2,
       clr
from p where sys_op_map_nonnull(clr) != sys_op_map_nonnull(cln)
...
Рейтинг: 0 / 0
Пятничная задача: Красное и черное
    #40018409
graycode
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Кобанчег
Здесь не удастся выкрутиться с decode + sum ибо цветов потенциально неограниченное множество.

не так изящно конечно и наверное можно упростить, но выкрутиться можно))
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
, t1 (x, c_src, c_tgt, gr_src, gr_tgt) as
(
select x1 as x
     , decode(flag, 'src', c, ''), decode(flag, 'tgt', c, '')
     , decode(flag, 'src', 1, 0), decode(flag, 'tgt', 1, 0)
from t
union all
select x2 + 1 as x
     , '', ''
     , decode(flag, 'src', 1, 0), decode(flag, 'tgt', 1, 0)
  from t
)
, t2 (x, c_src, c_tgt, gr_src, gr_tgt) as
(
select x, c_src, c_tgt
     , sum(gr_src) over (order by x range unbounded preceding)
     , sum(gr_tgt) over (order by x range unbounded preceding)
  from t1
)
, t3 (x, c) as
(
select x
     , coalesce(min(c_src) keep (dense_rank first order by x) over (partition by gr_src),
                min(c_tgt) keep (dense_rank first order by x) over (partition by gr_tgt))
  from t2
)
, t4 (x, c) as
(
select min(x), min(c) from (
    select x, c, sum(sog) over (order by x) as gr from (
        select x, c
             , case nvl(c, 'none') when nvl(lag(c) over (order by x), 'none') then 0 else 1 end as sog
          from t3))
group by gr
)
, t5 (x1, x2, c) as
(
select x
     , lead(x) over (order by x) - 1
     , c
  from t4
)
select * from t5 where x2 is not null order by x1
...
Рейтинг: 0 / 0
25 сообщений из 176, страница 1 из 8
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Пятничная задача: Красное и черное
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]