如何从表格中获取完整的树层次结构?

时间:2019-07-09 17:42:32

标签: sql postgresql

我有一个具有以下结构的表:

create table crosses (a varchar, b varchar);

带有示例数据:

insert into crosses values ('1','A');
insert into crosses values ('1','B');
insert into crosses values ('2','A');
insert into crosses values ('2','C');
insert into crosses values ('3','C');
insert into crosses values ('3','D');
insert into crosses values ('4','E');

我想获取完整的参考图,如下所示:

1 A
1 B
2 A
2 C
3 C
3 D

我正在尝试使用以下查询来实现这一目标:

WITH RECURSIVE cte AS
(
  SELECT
    a,
    b,
    FALSE revertRef
  FROM
    crosses
  WHERE
    a = '1'

  UNION

  SELECT
    c.a,
    c.b,
    (NOT cte.revertRef) revertRef
  FROM
    cte
    INNER JOIN crosses c ON 
      (CASE WHEN cte.revertRef THEN c.a ELSE c.b END) = (CASE WHEN cte.revertRef THEN cte.a ELSE cte.b END)      
)
SELECT * FROM cte WHERE revertRef ORDER BY a;

当表中的数据量很少时,查询工作很快,但是在生产中,我的表中有超过5000万条记录,因此查询执行时间过长(约10小时)。是否存在针对此类任务的解决方案?

1 个答案:

答案 0 :(得分:0)

我认为,无需像这样的递归查询就可以做到:

-- For multiple references of a:
SELECT a, b
FROM
(
    SELECT *
         , COUNT(*) OVER(PARTITION BY a) AS a_cnt
    FROM crosses
) temp
WHERE a_cnt > 1
ORDER BY a, b
;

-- For multiple references of a or b:
SELECT a, b
FROM
(
    SELECT *
         , COUNT(*) OVER(PARTITION BY a) AS a_cnt
         , COUNT(*) OVER(PARTITION BY b) AS b_cnt
    FROM crosses
) temp
WHERE a_cnt > 1 OR b_cnt > 1
ORDER BY a, b
;

db <>小提琴:Demo