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

Откуда:
Сообщений: 8
Здравствуйте всем!

Если возможно, подскажите, пожалуйста: не получается правильно решить следующие две задачи на использование регулярных выражений:

Задача 1.

Дана таблица из двух столбцов ACTION и CODE, в
каждом из которых хранятся списки чисел, разделённых пробелами. Создать запрос для разделения данных.

Например, для таблицы:

ACTIONCODE
1000 1100 900 841000 841100 841111
700 500 400 923400 923411


Результат должен быть:

N_LIST N_POS ACTION CODE
101000 1100 900 841000 841100 841111
11000841000
21100841100
3900841111
20700 500 400923400 923411
1700923400
2500 923411
3 400


В результате выборки приняты обозначения: N_LIST —
порядковый номер списка в исходной таблице, N_POS —
порядковый номер числа в списке.

Буду очень признательна за помощь))


И задача 2 тоже на использование регулярных выражений и тоже с числами):

Создать запрос для выбора из текста дробных чисел с разделителем дробной части в виде точки.
Тройки цифр целой и дробной части могут не отделяться или отделяться пробелом или запятой.
Совместное использование разных разделителей не допускается.


Спасибо заранее))
Марина
24 ноя 14, 10:36    [16894839]     Ответить | Цитировать Сообщить модератору
 Re: Запрос SQL/ использование регулярных выражений  [new]
Азагаш
Member

Откуда:
Сообщений: 450
Марина Marina
не получается правильно решить следующие две задачи

что значит не получается? судя по всему вы даже и не собирались их решать самостоятельно, иначе бы выложили свои варианты решения.
24 ноя 14, 10:46    [16894907]     Ответить | Цитировать Сообщить модератору
 Re: Запрос SQL/ использование регулярных выражений  [new]
Elic
Member

Откуда:
Сообщений: 29976
Марина Marina
Дана таблица из двух столбцов ACTION и CODE, в
каждом из которых хранятся списки чисел, разделённых пробелами.
Зачем студентов учат нарушать 1NF
24 ноя 14, 10:56    [16894984]     Ответить | Цитировать Сообщить модератору
 Re: Запрос SQL/ использование регулярных выражений  [new]
andreymx
Member

Откуда: Запорожье
Сообщений: 54370
Elic
Марина Marina
Дана таблица из двух столбцов ACTION и CODE, в
каждом из которых хранятся списки чисел, разделённых пробелами.
Зачем студентов учат нарушать 1NF
а где еще нужны регулярки в СУБД?
24 ноя 14, 10:59    [16895012]     Ответить | Цитировать Сообщить модератору
 Re: Запрос SQL/ использование регулярных выражений  [new]
Marishka25
Member

Откуда:
Сообщений: 150
возможно я не права и есть более простые способы решения стандартными средствами SQL (возможно есть какая-то обратная конструкция listagg), но я бы делала через функцию, которая принимала бы на вход параметры ACTION и CODE, а возвращала нужного вида коллекцию.
24 ноя 14, 15:59    [16897286]     Ответить | Цитировать Сообщить модератору
 Re: Запрос SQL/ использование регулярных выражений  [new]
MonteCarlos
Member

Откуда:
Сообщений: 547
with tbl as (
  select '1000 1100 900' action, '841000 841100 841111, 999999' code from dual union all
  select '700 500 400 800', '923400 923411' from dual
),
q as (
  select action, code,
         greatest (regexp_count(action, '\D*(\d+)\D*'), regexp_count(CODE, '\D*(\d+)\D*')) + 1 cnt 
  from tbl
)
select decode(n_pos, 0, rnk) n_list, n_pos, action, code
from (select n-1 n_pos,
             decode(n, 1, action, regexp_substr(action,'\D*(\d+)\D*', 1, n-1, 'i', 1)) action,   	 
             decode(n, 1, code, regexp_substr(code,'\D*(\d+)\D*', 1, n-1, 'i', 1)) code,
             dense_rank() over (order by action)  rnk
      from q, (select rownum n from dual connect by level <= (select max(cnt) from q))
      where cnt >= n)
order by rnk, n_pos 
24 ноя 14, 16:31    [16897559]     Ответить | Цитировать Сообщить модератору
 Re: Запрос SQL/ использование регулярных выражений  [new]
MonteCarlos
Member

Откуда:
Сообщений: 547
не предусмотрел вариант с одним числом, размножать же не надо, так точнее
with tbl as (
  select '1000' action, null code from dual union all
  select '700 500 400 800', '923400 923411' from dual
),
q as (
  select action, code,
         greatest ( nvl(regexp_count(action, '\D*(\d+)\D*'), 0), nvl(regexp_count(CODE, '\D*(\d+)\D*'),0)) + 1 cnt 
  from tbl
)
select decode(n_pos, 0, rnk) n_list, n_pos, action, code
from (select n-1 n_pos,
             decode(n, 1, action, regexp_substr(action,'\D*(\d+)\D*', 1, n-1, 'i', 1)) action,      
             decode(n, 1, code, regexp_substr(code,'\D*(\d+)\D*', 1, n-1, 'i', 1)) code,
             dense_rank() over (order by action)  rnk,
             max(n) over (partition by action) mx_n
      from q, (select rownum n from dual connect by level <= (select max(cnt) from q))
      where cnt >= n)
where decode (mx_n, 2, n_pos, 0) = 0      
order by rnk, n_pos 
24 ноя 14, 17:01    [16897778]     Ответить | Цитировать Сообщить модератору
 Re: Запрос SQL/ использование регулярных выражений  [new]
MonteCarlos
Member

Откуда:
Сообщений: 547
а этот даже с дублями корректно работает )))
with tbl as (
  select '923400 923411'   action, '923400 923411'  code from dual union all
  select '923400 923411' , '923400 923411'  from dual
),
q as (
  select action, code,
         nvl(regexp_count(action, '\D*(\d+)\D*'),0) cnt_a,
         nvl(regexp_count(code, '\D*(\d+)\D*'),0) cnt_c,
         greatest ( nvl(regexp_count(action, '\D*(\d+)\D*'), 0), nvl(regexp_count(code, '\D*(\d+)\D*'),0)) + 1 cnt 
  from tbl
)
select 
  decode(n_pos, 0, rnk) n_list, 
  n_pos, 
  action, 
  code
from (select t.*,
        dense_rank() over (order by part||rn_dubl) rnk,
        max(n_pos) over (partition by part||rn_dubl) mx_n_pos
      from (select n-1 n_pos,
                   decode(n, 1, action, regexp_substr(action,'\D*(\d+)\D*', 1, n-1, 'i', 1)) action,      
                   decode(n, 1, code, regexp_substr(code,'\D*(\d+)\D*', 1, n-1, 'i', 1)) code,
                   action||'-'||cnt_a||code||'-'||cnt_c as part,
                   row_number() over (partition by n||action||'-'||cnt_a||code||'-'||cnt_c order by rownum) rn_dubl
            from q, (select rownum n from dual connect by level <= (select max(cnt) from q))
            where cnt >= n) t )
      where decode (mx_n_pos, 1, n_pos, 0) = 0      
order by rnk, n_pos 
24 ноя 14, 17:42    [16898048]     Ответить | Цитировать Сообщить модератору
 Re: Запрос SQL/ использование регулярных выражений  [new]
Марина Marina
Member

Откуда:
Сообщений: 8
спасибо)), Monte Carlos, я подключюсь сегодня ближе к ночи к базе данных, проверю, у меня к Вам будет несколько вопросов наверное по поводу этого запроса)) я напишу позже ))
24 ноя 14, 17:57    [16898150]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: Запрос SQL/ использование регулярных выражений  [new]
nightwish1
Member

Откуда:
Сообщений: 14
MonteCarlos, как сделать ту же задачу без использования аналитических функций?
13 дек 15, 20:20    [18554666]     Ответить | Цитировать Сообщить модератору
 Re: Запрос SQL/ использование регулярных выражений  [new]
SY
Member

Откуда: Middlebury, CT USA
Сообщений: 10039
nightwish1
как сделать ту же задачу без использования аналитических функций?


with tbl as (
             select '1000 1100 900' action, '841000 841100 841111' code from dual union all
             select '700 500 400', '923400 923411' from dual
            ),
       t as (
             select  rownum rn,
                     action,
                     code
               from  tbl
            )
select  case column_value
          when 0 then rn
        end n_list,
        column_value n_pos,
        case column_value
          when 0 then action
          else regexp_substr(action,'[^ ]+',1,column_value)
        end action,
        case column_value
          when 0 then code
          else regexp_substr(code,'[^ ]+',1,column_value)
        end code
  from  t,
        table(
              cast(
                   multiset(
                            select  level - 1
                              from  dual
                              connect by level <= greatest(nvl(regexp_count(action,' '),0),nvl(regexp_count(code,' '),0)) + 2
                           )
                                 as sys.OdciNumberList
                  )
              )
  where column_value = 0
     or nvl(action,code) is not null
  order by rn,
           column_value
/

    N_LIST      N_POS ACTION        CODE
---------- ---------- ------------- --------------------
         1          0 1000 1100 900 841000 841100 841111
                    1 1000          841000
                    2 1100          841100
                    3 900           841111
         2          0 700 500 400   923400 923411
                    1 700           923400
                    2 500           923411
                    3 400

8 rows selected.

SQL>


SY.

Сообщение было отредактировано: 13 дек 15, 23:07
13 дек 15, 21:27    [18554832]     Ответить | Цитировать Сообщить модератору
 Re: Запрос SQL/ использование регулярных выражений  [new]
nightwish1
Member

Откуда:
Сообщений: 14
SY, большое Вам спасибо. Теперь разобрался.
13 дек 15, 22:58    [18555143]     Ответить | Цитировать Сообщить модератору
 Re: Запрос SQL/ использование регулярных выражений  [new]
SY
Member

Откуда: Middlebury, CT USA
Сообщений: 10039
nightwish1
Теперь разобрался.


Только учти порядковый номер списка в исходной таблице N_LIST шит белыми нитками. В реляционных таблицах нет порядка строк, посему без поля или выражения задающего порядок строк N_LIST большого смысла не имеет. Например, ROWNUM который я использовал может поменяться при следующем выполнении.

SY.
13 дек 15, 23:05    [18555173]     Ответить | Цитировать Сообщить модератору
 Re: Запрос SQL/ использование регулярных выражений  [new]
nightwish1
Member

Откуда:
Сообщений: 14
SY, а можно как-нибудь без cast и multiset обойтись?
Приведите, пожалуйста, пример кода.
14 дек 15, 01:20    [18555436]     Ответить | Цитировать Сообщить модератору
 Re: Запрос SQL/ использование регулярных выражений  [new]
SY
Member

Откуда: Middlebury, CT USA
Сообщений: 10039
nightwish1
а можно как-нибудь без cast и multiset обойтись?


with tbl as (
             select '1000 1100 900' action, '841000 841100 841111' code from dual union all
             select '700 500 400', '923400 923411' from dual
            ),
       t as (
             select  rownum rn,
                     action,
                     code
               from  tbl
            )
select  case n_pos
          when 0 then rn
        end n_list,
        n_pos,
        case n_pos
          when 0 then action
          else regexp_substr(action,'[^ ]+',1,n_pos)
        end action,
        case n_pos
          when 0 then code
          else regexp_substr(code,'[^ ]+',1,n_pos)
        end code
  from  t,
        xmltable(
                 '0 to xs:integer($s)'
                 passing greatest(nvl(regexp_count(action,' '),0),nvl(regexp_count(code,' '),0)) + 1 as "s"
                 columns
                   n_pos number path '.'
                )
  where n_pos = 0
     or nvl(action,code) is not null
  order by rn,
           n_pos
/

    N_LIST      N_POS ACTION        CODE
---------- ---------- ------------- --------------------
         1          0 1000 1100 900 841000 841100 841111
                    1 1000          841000
                    2 1100          841100
                    3 900           841111
         2          0 700 500 400   923400 923411
                    1 700           923400
                    2 500           923411
                    3 400

8 rows selected.

SQL>


SY.
14 дек 15, 03:42    [18555517]     Ответить | Цитировать Сообщить модератору
 Re: Запрос SQL/ использование регулярных выражений  [new]
Alexander_S1
Member

Откуда:
Сообщений: 9
SY, спасибо. А можно простым SELECT-ом? Я xmltable не проходил.
14 дек 15, 11:12    [18556303]     Ответить | Цитировать Сообщить модератору
 Re: Запрос SQL/ использование регулярных выражений  [new]
нет предела пустоты
Guest
Alexander_S1
А можно простым SELECT-ом? Я xmltable не проходил.
Фраза предполагает, что "простой SELECT" ты проходил. С чего ожидания, что очередной ответ окажется достаточно простым для твоих способностей?
14 дек 15, 12:34    [18556749]     Ответить | Цитировать Сообщить модератору
 Re: Запрос SQL/ использование регулярных выражений  [new]
SY
Member

Откуда: Middlebury, CT USA
Сообщений: 10039
Alexander_S1
А можно простым SELECT-ом? Я xmltable не проходил.


with tbl as (
             select '1000 1100 900' action, '841000 841100 841111' code from dual union all
             select '700 500 400', '923400 923411' from dual
            ),
       t as (
             select  rownum rn,
                     action,
                     code
               from  tbl
            )
select  case level
          when 1 then rn
        end n_list,
        level - 1 n_pos,
        case level
          when 1 then action
          else regexp_substr(action,'[^ ]+',1,level - 1)
        end action,
        case level
          when 1 then code
          else regexp_substr(code,'[^ ]+',1,level - 1)
        end code
  from  t
  connect by rn = prior rn
         and level <= greatest(nvl(regexp_count(action,' '),0),nvl(regexp_count(code,' '),0)) + 2
         and prior sys_guid() is not null
  order by rn,
           level
/

    N_LIST      N_POS ACTION        CODE
---------- ---------- ------------- --------------------
         1          0 1000 1100 900 841000 841100 841111
                    1 1000          841000
                    2 1100          841100
                    3 900           841111
         2          0 700 500 400   923400 923411
                    1 700           923400
                    2 500           923411
                    3 400

8 rows selected.

SQL>


SY.

Сообщение было отредактировано: 14 дек 15, 16:46
14 дек 15, 16:45    [18558493]     Ответить | Цитировать Сообщить модератору
 Re: Запрос SQL/ использование регулярных выражений  [new]
MasterZiv
Member

Откуда: Питер
Сообщений: 34630
Марина Marina
спасибо)), Monte Carlos, я подключюсь сегодня ближе к ночи к базе данных, проверю, у меня к Вам будет несколько вопросов наверное по поводу этого запроса)) я напишу позже ))


конечно, спасибо, он написал, а зарплату - тебе... я бы на месте тебя бы этому Карлосу пива, либо как еще, отблагодарил бы в не материальной форме...
17 дек 15, 07:57    [18571120]     Ответить | Цитировать Сообщить модератору
 Re: Запрос SQL/ использование регулярных выражений  [new]
туперь_
Guest
ты больше года жил с глухой обидой за Карлоса... но не смог все же переварить это и поэтому выплеснул

зы
мы не на форуме кандидатов в машинистки, можно не демонстрировать столь феноменальную производительность.
17 дек 15, 08:22    [18571160]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить