Динамическое самостоятельное перекрестное соединение SQL с использованием TSql - PullRequest
0 голосов
/ 12 октября 2018

У меня есть таблица с такими данными

Group    Value  
1        A  
1        B  
1        C  
2        F  
2        G  
3        J
3        K

Я хочу объединить всех членов одной группы со всеми членами каждой из других групп в один столбец, подобный этому:

AFJ
AFK
AGJ
AGK
BFJ
BFK
BGJ
BGK
CFJ
CFK
CGJ
CGK

Может быть n групп и n значений

Спасибо

Ответы [ 2 ]

0 голосов
/ 12 октября 2018

SQL не предлагает много вариантов для такого запроса.Единственным стандартным методом является рекурсивный CTE.Другие методы могут включать в себя рекурсивные функции или хранимые процедуры.

Ниже приведен пример рекурсивного CTE, который решает эту проблему:

with groups as (
      select v.*
      from (values (1, 'a'), (1, 'b'), (1, 'c'), (2, 'f'), (2, 'g'), (3, 'h'), (3, 'k')
           ) v(g, val)
     ),
     cte as (
      select 1 as groupid, val, 1 as lev
      from groups
      where g = 1
      union all
      select cte.groupid + 1, cte.val + g.val, lev + 1
      from cte join
           groups g
           on g.g = cte.groupid + 1
     )
select val
from (select cte.*, max(lev) over () as max_lev
      from cte
     ) cte
where lev = max_lev
order by 1;

Некоторые базы данных, поддерживающие рекурсивные CTE, не используютrecursive ключевое слово.

Вот дБ <> скрипка .

0 голосов
/ 12 октября 2018

Если вам необходимо учесть пропуски между группами, то есть группа 1, затем нет 2, а затем 3.

with t(Grp, val) as (
    select 1,        'A'  from dual
    union all
    select 1,        'B'    from dual
    union all
    select 1,        'C'    from dual
    union all
    select 2,        'F'    from dual
    union all
    select 2,        'G'    from dual
    union all
    select 3,        'J'  from dual
    union all
    select 3,        'K'  from dual
)

, grpIndexes as (
    SELECT ROWNUM indx
         , grp
     FROM (select distinct          
                  grp
             from t)
)

, Grps as (
    select t.*
         , grpIndexes.indx
      from t
     inner join grpIndexes
        on grpIndexes.grp = t.grp
)

, rt(val, indx, lvl) as (
    select val
         , indx
         , 0 as lvl
      from Grps
     where indx = (select min(indx) from Grps)
  union all
    select previous.val || this.val as val
         , this.indx
         , previous.lvl + 1 as lvl
      from rt previous
         , Grps this
     where this.indx = (select min(indx) from Grps where indx > previous.indx)
       and previous.indx <> (select max(indx) from Grps)
)

select val
  from rt
 where lvl = (select max(lvl) from rt)
  order by val
;

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

...