Как я могу соединить вложенные строки в - проблема рекурсии в SQL? - PullRequest
0 голосов
/ 30 марта 2020

Я хочу назначить KEY для двух столбцов ID и PARAM. Все строки с одинаковым идентификатором должны иметь одинаковый ключ. Строки связаны между собой двумя столбцами, что означает, что ID = 1 связан с ID = 2 с помощью PARAM = A. ID = 2 связан с ID = 3 с помощью PARAM = D, а также с ID = 4 с помощью PARAM = D. ID = 5 связан с ID = 4 с помощью PARAM = W. ... ID = 8 связан с ID = 4 с помощью PARAM = AA

Вот примерные входные данные, реальные данные более вложенные

ID   PARAM  KEY Excepted result 
1    A      1-A
1    C      1-A
2    A      1-A
2    C      1-A
2    D      1-A
3    D      1-A
4    AA     1-A
4    D      1-A
4    K      1-A
4    T      1-A
4    W      1-A
4    Z      1-A
5    W      1-A
6    W      1-A
7    T      1-A
8    AA     1-A
10   FF     10-FF
15   G      15-G
99   FF     10-FF

Я пытался с какой-то группой операций, min (), max (), но я не могу получить исключительные результаты. Есть ли у вас какие-либо предложения, как я могу получить столбец KEY с SQL на Oracle?

1 Ответ

0 голосов
/ 05 апреля 2020

Вероятно, есть много способов сделать это, но для меня это выглядит как проблема, которую лучше всего решить с помощью CONNECT BY.

Я создал таблицу с именем "mytable" с вашими примерами данных и написал пример запроса, который возвращает ожидаемые результаты.

Outline:

  • Мы начинаем с любой строки и подключаемся к другой строке на основе того же идентификатора или PARAM.
  • Использование ключевое слово NOCYCLE предотвращает циклы.
  • Функция CONNECT_BY_ ROOT выбирает значение из строки, с которой мы начали.
  • Однако внутренний запрос возвращает больше строк, чем мы хотим. Например, [4, D] имеет [3, D] как «root», но мы хотим отследить его как можно дальше до [1, A].
  • Итак, по порядку чтобы уменьшить строки, мы используем функцию row_number () analyti c для нумерации каждого "root" для данной пары id / param.
  • Затем мы выбираем только те результаты, где номер строки (r1 ) равен единице.
  • И, наконец, результаты сортируются по значениям id и param.
select id, param, rootid||'-'||rootparam as "Expected result" from (
select  row_number() over (partition by id, param order by rootid, rootparam) r1,
    rootid, rootparam, id, param from (
        select connect_by_root(id) rootid, connect_by_root(param) rootparam,
            id, param
        from mytable
        connect by nocycle (prior param =param and prior id <> id)
                        or (prior id = id and prior param <> param)
        order by connect_by_root(id), connect_by_root(param)
    )
) where r1 = 1
order by to_number(id), param

Отказ от ответственности: Это пример для информационных целей и не предназначен для оптимизации или оптимизации SQL. Неуместно использовать как есть для вашего производственного приложения или домашнего задания. Используйте EXPLAIN PLAN, чтобы увидеть, насколько оптимизатор оправдан, и если у вас большие объемы данных и вы беспокоитесь о скорости, измерьте время, затрачиваемое вашими альтернативными запросами, а не угадывайте, что быстрее.

Вот инициализация для тестовых данных:

create table mytable as
select '1' ID,'A' PARAM from dual -- 1-A
union all select '1' ID,'C' PARAM from dual -- 1-A
union all select '2' ID,'A' PARAM from dual -- 1-A
union all select '2' ID,'C' PARAM from dual -- 1-A
union all select '2' ID,'D' PARAM from dual -- 1-A
union all select '3' ID,'D' PARAM from dual -- 1-A
union all select '4' ID,'AA' PARAM from dual -- 1-A
union all select '4' ID,'D' PARAM from dual -- 1-A
union all select '4' ID,'K' PARAM from dual -- 1-A
union all select '4' ID,'T' PARAM from dual -- 1-A
union all select '4' ID,'W' PARAM from dual -- 1-A
union all select '4' ID,'Z' PARAM from dual -- 1-A
union all select '5' ID,'W' PARAM from dual -- 1-A
union all select '6' ID,'W' PARAM from dual -- 1-A
union all select '7' ID,'T' PARAM from dual -- 1-A
union all select '8' ID,'AA' PARAM from dual -- 1-A
union all select '10' ID,'FF' PARAM from dual -- 10-FF
union all select '15' ID,'G' PARAM from dual -- 15-G
union all select '99' ID,'FF' PARAM from dual -- 10-FF
...