Oracle: возможно ли обрезать строку, подсчитать количество вхождений и вставить в новую таблицу? - PullRequest
0 голосов
/ 02 января 2019

Моя исходная таблица выглядит так:

id|value|count

Значение - это строка значений, разделенных точкой с запятой (;). Например, это может выглядеть так

A;B;C;D;

Некоторые могут не иметь значений в определенной позиции, например

A;;;D;

Во-первых, я выборочно переместил записи в новую таблицу (targettable), основываясь на позициях со значениями, используя regexp. Я добился этого, используя [^;]+; для получения некоторого значения между точками с запятой, и [^;]*; для тех позиций, которые меня не интересуют. Например, если бы я хотел, чтобы 1-е и 4-е места имели значения, я мог бы включить регулярное выражение со вставкой в ​​вот так

insert into
    targettable tt (id, value, count)
    SELECT some_seq.nextval,value, count
    FROM source table
    WHERE
    regexp_like(value, '^[^;]+;[^;]*;[^;]*;[^;]+;')

так что теперь в моей новой таблице есть список записей, значения которых находятся на 1-й и 4-й позиции. Это может выглядеть так

1|A;B;C;D;|2
2|B;;;E;|1
3|A;D;;D|3

Далее есть 2 вещи, которые я хочу сделать. 1. избавиться от ценностей, отличных от 1-го и 4-го. 2. объединить одинаковые значения и сложить их количество. Например, записи 1 и 3 одинаковы, поэтому я хочу обрезать их, чтобы они стали A; D;, а затем добавить их счет, так что 2 + 3 = 5. Теперь моя новая таблица выглядит так

1|A;D;|5
2|B;E;|1

Пока я могу каким-то образом добраться до финального стола из исходной таблицы, мне нет дела до шагов. Промежуточная таблица не обязательна, но она может помочь мне достичь конечного результата. Я не уверен, смогу ли я пойти дальше с Оркалом, хотя. Если нет, мне придется перемещать и обрабатывать записи с помощью Java. Имейте в виду, что у меня есть миллионы записей, поэтому я бы рассмотрел метод Oracle, если это возможно.

Ответы [ 2 ]

0 голосов
/ 02 января 2019

Я бы использовал regexp_replace для удаления 2-й и 3-й частей строки в сочетании с агрегированным запросом для получения общего количества, например:

SELECT
    regexp_replace(value, '^[^;]+;([^;]*;[^;]*;)[^;]+;', ''),
    SUM(count)
FROM source table
WHERE
    regexp_like(value, '^[^;]+;[^;]*;[^;]*;[^;]+;')
GROUP BY
    regexp_replace(value, '^[^;]+;([^;]*;[^;]*;)[^;]+;', '')
0 голосов
/ 02 января 2019

Вы должны быть в состоянии пропустить промежуточную таблицу;просто извлеките 1-й и 4-й элементы, используя функцию regexp_substr() , проверяя, чтобы они не были нулевыми:

select regexp_substr(value, '(.*?)(;|$)', 1, 1, null, 1) -- first position
  || ';' || regexp_substr(value, '(.*?)(;|$)', 1, 4, null, 1) -- fourth position
  || ';' as value, -- if you want trailing semicolon
  count
from source
where regexp_substr(value, '(.*?)(;|$)', 1, 1, null, 1) is not null
and regexp_substr(value, '(.*?)(;|$)', 1, 4, null, 1) is not null;

VALUE                   COUNT
------------------ ----------
A;D;                        2
B;E;                        1
A;D;                        3

, а затем агрегируйте эти результаты:

select value, sum(count) as count
from (
  select regexp_substr(value, '(.*?)(;|$)', 1, 1, null, 1) -- first position
    || ';' || regexp_substr(value, '(.*?)(;|$)', 1, 4, null, 1) -- fourth position
    || ';' as value, -- if you want trailing semicolon
    count
  from source
  where regexp_substr(value, '(.*?)(;|$)', 1, 1, null, 1) is not null
  and regexp_substr(value, '(.*?)(;|$)', 1, 4, null, 1) is not null
)
group by value;

VALUE                   COUNT
------------------ ----------
A;D;                        5
B;E;                        1

Тогда для вашей вставки вы можете использовать этот запрос, либо с идентификатором автоинкремента (12c +), либо с помощью установки идентификатора из последовательности с помощью триггера, либо, возможно, в другом уровне подзапроса, чтобы получить значение явно:

insert into target (id, value, count)
select some_seq.nextval, value, count
from (
  select value, sum(count) as count
  from (
    select regexp_substr(value, '(.*?)(;|$)', 1, 1, null, 1) -- first position
      || ';' || regexp_substr(value, '(.*?)(;|$)', 1, 4, null, 1) -- fourth position
      || ';' as value, -- if you want trailing semicolon
      count
    from source
    where regexp_substr(value, '(.*?)(;|$)', 1, 1, null, 1) is not null
    and regexp_substr(value, '(.*?)(;|$)', 1, 4, null, 1) is not null
  )
  group by value
);

Если вы создаете для этого новую последовательность, поэтому они начинаются с 1, вы можете использовать rownum или row_number().


Кстати, используяключевое слово или имя функции, например count, поскольку имя столбца сбивает с толку (sum(count)!?);это могут быть не ваши настоящие имена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...