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

Откуда:
Сообщений: 91
Добрый вечер! Очень нужна помощь специалистов по работе с Oracle PL/SQL. Есть следующая задача. На входе имеем строку следующего типа [1]=[30];[2,3]>[4,5];[100,200]<[1,2,3];.....[]. Длина строки за ранее не известна. С этой строки необходимо получить перечень наборов следующего типа:
Пример в приложение.

перебираем все варианты. по такому принципу. Может кто то сталкивался или возможно у кого то есть какой алгоритм, как реализовать данную задачу.

Очень буду благодарен за помощь.

К сообщению приложен файл. Размер - 4Kb
24 окт 19, 23:59    [22002142]     Ответить | Цитировать Сообщить модератору
 Re: Создание наборов с помощью запроса  [new]
Кобанчег
Member

Откуда: Рахів
Сообщений: 837
Сергей_1991,

SQL> with t(str) as
  2   (select '[1]=[30];[2,3]>[4,5];[100,200]<[1,2,3]' from dual)
  3  select sys_connect_by_path(sl.l || '=' || sr.r, ' ') x
  4  from
  5  (
  6  select rownum id,
  7         regexp_substr(str, '\[([[:digit:],]+)\]', 1, level * 2 - 1, null, 1) l,
  8         regexp_substr(str, '\[([[:digit:],]+)\]', 1, level * 2, null, 1) r
  9    from t
 10  connect by level < regexp_count(str, ';') + 2
 11  )
 12   cross apply (select regexp_substr(l, '\d+', 1, level) l from dual connect by level <= regexp_count(l, ',') + 1) sl
 13   cross apply (select regexp_substr(r, '\d+', 1, level) r from dual connect by level <= regexp_count(r, ',') + 1) sr
 14   where connect_by_isleaf = 1
 15   start with id = 1
 16  connect by prior id + 1 = id;

X
--------------------------------------------------------------------------------
 1=30 2=4 100=1
 1=30 2=4 100=2
 1=30 2=4 100=3
 1=30 2=4 200=1
 1=30 2=4 200=2
 1=30 2=4 200=3
 1=30 2=5 100=1
 1=30 2=5 100=2
 1=30 2=5 100=3
 1=30 2=5 200=1
 1=30 2=5 200=2
 1=30 2=5 200=3
 1=30 3=4 100=1
 1=30 3=4 100=2
 1=30 3=4 100=3
 1=30 3=4 200=1
 1=30 3=4 200=2
 1=30 3=4 200=3
 1=30 3=5 100=1
 1=30 3=5 100=2
 1=30 3=5 100=3
 1=30 3=5 200=1
 1=30 3=5 200=2
 1=30 3=5 200=3

24 rows selected.
25 окт 19, 00:44    [22002152]     Ответить | Цитировать Сообщить модератору
 Re: Создание наборов с помощью запроса  [new]
Сергей_1991
Member

Откуда:
Сообщений: 91
Кобанчег, добрый день! При запуске данного запроса выдает ошибку ora-00904: r invalid identifier.
Версия oracle 11g enterprise edition release 11.2.0.4.0.
25 окт 19, 10:42    [22002319]     Ответить | Цитировать Сообщить модератору
 Re: Создание наборов с помощью запроса  [new]
env
Member

Откуда: Россия, Москва
Сообщений: 6693
Сергей_1991,

на 11.2 этот запрос не взлетит
25 окт 19, 11:24    [22002366]     Ответить | Цитировать Сообщить модератору
 Re: Создание наборов с помощью запроса  [new]
Сергей_1991
Member

Откуда:
Сообщений: 91
env, добрый день! Возможно у Вас есть идеи как это можно реализовать на версии 11.2?
25 окт 19, 11:43    [22002388]     Ответить | Цитировать Сообщить модератору
 Re: Создание наборов с помощью запроса  [new]
Кобанчег
Member

Откуда: Рахів
Сообщений: 837
Сергей_1991
Возможно у Вас есть
Но ведь идея была показана.
Возможно стоит переформулировать вопрос: "Я даже не пытаюсь думать, сделайте всё за меня".
А не идеи спрашивать и алгоритмы.
25 окт 19, 12:01    [22002409]     Ответить | Цитировать Сообщить модератору
 Re: Создание наборов с помощью запроса  [new]
Сергей_1991
Member

Откуда:
Сообщений: 91
Кобанчег, я попробыл сделать вот такой вариант
with t(str) as
   (select '[1]=[30];[2,3]>[4,5]' from dual),
   
 tt as (
 select rownum idlvl0,
         regexp_substr(str, '\[([[:digit:],]+)\]', 1, level * 2 - 1, null, 1) l,
         regexp_substr(str, '\[([[:digit:],]+)\]', 1, level * 2, null, 1) r
     from t 
      connect by level < regexp_count(str, ';') + 2
      )--,
      --select * from tt
     
      
      
      
      select distinct  sys_connect_by_path(sl.l || '=' || sr.r, ' ') x
   from  (select rownum idlvl0,
          regexp_substr(str, '\[([[:digit:],]+)\]', 1, level * 2 - 1, null, 1) l,
          regexp_substr(str, '\[([[:digit:],]+)\]', 1, level * 2, null, 1)           
         from t 
         connect by level < regexp_count(str, ';') + 2) t
      
   cross join  (select regexp_substr(l, '\d+', 1, level) l from tt connect by level <= regexp_count(l, ',') + 1) sl
   cross join (select regexp_substr(r, '\d+', 1, level) r from tt connect by level <= regexp_count(r, ',') + 1) sr
    where connect_by_isleaf = 1
    start with  idlvl0 = 1
    connect by prior  idlvl0 + 1 =  idlvl0
    order by 1

но это не работает , так как у вас. Я пока не особо силен в знании специфических вещей в Oracle. Мне не понятно пока, как можно отсеять не нужные данный
25 окт 19, 12:07    [22002422]     Ответить | Цитировать Сообщить модератору
 Re: Создание наборов с помощью запроса  [new]
Сергей_1991
Member

Откуда:
Сообщений: 91
я уже неделю бьюсь над решением этой задачи и пока без успешно. А руководство требует решений, по этому и прошу о помощи
25 окт 19, 12:09    [22002426]     Ответить | Цитировать Сообщить модератору
 Re: Создание наборов с помощью запроса  [new]
Кобанчег
Member

Откуда: Рахів
Сообщений: 837
Сергей_1991
Я пока не особо силен в знании специфических вещей в Oracle.
Ну раз ты тогадался, что дело в cross apply найди способ размножить строки без него.
Для этого не надо коверкать весь запрос, пихать туда distinct и прочее.

Ты вообще не объяснил зачем тебе это надо.
И какой смысл использовать код если ты не в состоянии его понять и поддерживать.
25 окт 19, 12:16    [22002439]     Ответить | Цитировать Сообщить модератору
 Re: Создание наборов с помощью запроса  [new]
Кобанчег
Member

Откуда: Рахів
Сообщений: 837
Сергей_1991
я уже неделю бьюсь над решением этой задачи и пока без успешно. А руководство требует решений, по этому и прошу о помощи
Ты просил идею или алгоритм.
Это можно было предоставить тебе в словесной форме.

Вместо этого был предоставлен конкретный код, работающий на 12c+.
И даже тут ты не в состянии сделать минимальное изменение.

Вместо хаотических маразматических изменений общего запроса подумай как можно переписать запрос ниже без cross apply.
SQL> with t(str) as (select '100,200' from dual)
  2  select x
  3    from t
  4   cross apply (select regexp_substr(str, '\d+', 1, level) x
  5                  from t
  6                connect by level <= regexp_count(str, ',') + 1);

X
----------------------------
100
200
Можно даже не думать, а воспользоваться поиском по форуму.
25 окт 19, 12:24    [22002455]     Ответить | Цитировать Сообщить модератору
 Re: Создание наборов с помощью запроса  [new]
Сергей_1991
Member

Откуда:
Сообщений: 91
Кобанчег, Задача следующаю - мне приходит ексель с набором полей. В ячейках екселя хранятся вот такие наборы разной длины и с разными условиями. Мне необходимо эти наборы натравить на запрос с базисными данными и получить выходной результат. Я c Oracle работаю пару месяцев, до этого 6 лет работал с ms sql. думаю как то разберусь с поддерживанием кода. А про специфические вещи - я имею ввиду например start with idlvl0 = 1 connect by prior idlvl0 + 1 = idlvl0, которые я пока полностью не изучил (изучаю по необходимости).

Спасибо большое за помощь и идею. Буду дальше доделывать запрос
25 окт 19, 12:25    [22002461]     Ответить | Цитировать Сообщить модератору
 Re: Создание наборов с помощью запроса  [new]
Кобанчег
Member

Откуда: Рахів
Сообщений: 837
Сергей_1991
Я c Oracle работаю пару месяцев, до этого 6 лет работал с ms sql. думаю как то разберусь с поддерживанием кода. А про специфические вещи - я имею ввиду например start with idlvl0 = 1 connect by prior idlvl0 + 1 = idlvl0, которые я пока полностью не изучил
Тогда должен суметь перебрать все варинты с помощью Recursive CTE вместо connect by.
25 окт 19, 12:33    [22002468]     Ответить | Цитировать Сообщить модератору
 Re: Создание наборов с помощью запроса  [new]
Сергей_1991
Member

Откуда:
Сообщений: 91
Кобанчег
Сергей_1991
я уже неделю бьюсь над решением этой задачи и пока без успешно. А руководство требует решений, по этому и прошу о помощи
Ты просил идею или алгоритм.
Это можно было предоставить тебе в словесной форме.

Вместо этого был предоставлен конкретный код, работающий на 12c+.
И даже тут ты не в состянии сделать минимальное изменение.

Вместо хаотических маразматических изменений общего запроса подумай как можно переписать запрос ниже без cross apply.
SQL> with t(str) as (select '100,200' from dual)
  2  select x
  3    from t
  4   cross apply (select regexp_substr(str, '\d+', 1, level) x
  5                  from t
  6                connect by level <= regexp_count(str, ',') + 1);

X
----------------------------
100
200
Можно даже не думать, а воспользоваться поиском по форуму.



Поверьте, как распарсить строки я написал еще в первый день как получил задачу. У меня проблему составило перемножить и получить наборы. У меня не было идее как выбирать данные из набор и брать только одно значение.
25 окт 19, 12:34    [22002469]     Ответить | Цитировать Сообщить модератору
 Re: Создание наборов с помощью запроса  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 51752

Сергей_1991
мне приходит ексель с набором полей

Раз тебе приходит эксель, так парсь эти наборы средствами экселя и не морщь моск оракулу,
которые для этого не предназначен.

Posted via ActualForum NNTP Server 1.5

25 окт 19, 12:35    [22002471]     Ответить | Цитировать Сообщить модератору
 Re: Создание наборов с помощью запроса  [new]
Сергей_1991
Member

Откуда:
Сообщений: 91
Dimitry Sibiryakov
Сергей_1991
мне приходит ексель с набором полей

Раз тебе приходит эксель, так парсь эти наборы средствами экселя и не морщь моск оракулу,
которые для этого не предназначен.


Ексель может быть большой. И если начинать парсить в нем , может просто все зависнуть.
25 окт 19, 12:38    [22002475]     Ответить | Цитировать Сообщить модератору
 Re: Создание наборов с помощью запроса  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 51752

Сергей_1991
если начинать парсить в нем , может просто все зависнуть.

А может и не зависнуть. Всё дело в волшебных пузырьках руках программиста.

Posted via ActualForum NNTP Server 1.5

25 окт 19, 12:44    [22002477]     Ответить | Цитировать Сообщить модератору
 Re: Создание наборов с помощью запроса  [new]
Кобанчег
Member

Откуда: Рахів
Сообщений: 837
Сергей_1991
Поверьте, как распарсить строки я написал еще в первый день как получил задачу.
Если б ты понимал, то не показывал бы то уродство с cross join.
25 окт 19, 12:44    [22002480]     Ответить | Цитировать Сообщить модератору
 Re: Создание наборов с помощью запроса  [new]
Misha111
Member

Откуда:
Сообщений: 19
with t(str) as
 (select '[1]=[30];[2,3]>[4,5];[100,200]<[1,2,3]' from dual)
, a as (
select rownum id,
       regexp_substr(str, '\[([[:digit:],]+)\]', 1, level * 2 - 1, null, 1) l,
       regexp_substr(str, '\[([[:digit:],]+)\]', 1, level * 2, null, 1) r
  from t
connect by level < regexp_count(str, ';') + 2
)
, sl as (
select distinct id,
       regexp_substr(l, '\d+', 1, level) l
from a
connect by level <= regexp_count(l, ',') + 1
)
, sr as (
select distinct id,
       regexp_substr(r, '\d+', 1, level) r
from a
connect by level <= regexp_count(r, ',') + 1
)
--select *
select sys_connect_by_path(sl.l || '=' || sr.r, ' ') x
from a, sl, sr
where a.id=sl.id and a.id=sr.id
and connect_by_isleaf = 1
 start with a.id = 1
connect by prior a.id + 1 = a.id;
25 окт 19, 13:46    [22002571]     Ответить | Цитировать Сообщить модератору
 Re: Создание наборов с помощью запроса  [new]
Misha111
Member

Откуда:
Сообщений: 19
если "влоб" переписать запрос Кобанчег`а наверно получится так
with t(str) as
 (select '[1]=[30];[2,3]>[4,5];[100,200]<[1,2,3]' from dual)
select sys_connect_by_path(sl.COLUMN_VALUE || '=' || sr.COLUMN_VALUE, ' ') x
--select *
from
(
select rownum id,
       regexp_substr(str, '\[([[:digit:],]+)\]', 1, level * 2 - 1, null, 1) l,
       regexp_substr(str, '\[([[:digit:],]+)\]', 1, level * 2, null, 1) r
  from t
connect by level < regexp_count(str, ';') + 2
),
-- cross apply (select regexp_substr(l, '\d+', 1, level) l from dual connect by level <= regexp_count(l, ',') + 1) sl
 table(cast(multiset(select regexp_substr(l, '\d+', 1, level) l from dual connect by level <= regexp_count(l, ',') + 1) as sys.odcivarchar2list)) sl,
 table(cast(multiset(select regexp_substr(r, '\d+', 1, level) r from dual connect by level <= regexp_count(r, ',') + 1) as sys.odcivarchar2list)) sr
 where connect_by_isleaf = 1
 start with id = 1
connect by prior id + 1 = id;
25 окт 19, 13:49    [22002579]     Ответить | Цитировать Сообщить модератору
 Re: Создание наборов с помощью запроса  [new]
Сергей_1991
Member

Откуда:
Сообщений: 91
Кобанчег, спасибо за помощь, все получилось! Очень помог Ваш вариант решения, чтобы разобраться в логике как перемножать!
25 окт 19, 15:12    [22002716]     Ответить | Цитировать Сообщить модератору
 Re: Создание наборов с помощью запроса  [new]
Сергей_1991
Member

Откуда:
Сообщений: 91
Misha111, спасибо большое, только увидел Ваше решение, проверил, тоже подходит. Спасибо за помощь!
25 окт 19, 15:14    [22002718]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить