使用TSql的SQL动态自交叉联接

时间:2018-10-12 00:08:24

标签: sql cross-join

我有一个表,其中包含这样的数据

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 :(得分:2)

SQL没有为此类查询提供许多选项。一种标准方法是递归CTE。其他方法可能涉及递归函数或存储过程。

以下是解决此问题的递归CTE的示例:

<p>Order Placed at: {{ momentjs(order.created_at).tz('Africa/Cairo').format('DD-MM-YYYY @ hh:mm a') }}</p>

某些支持递归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; 关键字。

这里是db<>fiddle

答案 1 :(得分:0)

如果您需要考虑各组之间的差距,即第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
;

请注意,我重命名了列,因为“组”和“值”是保留字。