写一个查询 returns all parents on the top and then children

Write a query that returns all parents on top and then children

Table结构:

|--------------------------------|-------------|
|branchid   |branchcode |parentid|branchtypeid |
|-----------------------|--------|-------------|
|438        |UKHQR      |438     |  2          |
|-----------|-----------|--------|-------------|
|539        |UKBRS      |438     |  1          |
|-----------|-----------|--------|-------------|
|3683       |UKSNL      |438     |  2          |
|-----------|-----------|--------|-------------|
|3110       |UKNNX      |3683    |  1          |
|-----------|-----------|--------|-------------|
|987        |FNOLR      |987     |  2          |
|-----------|-----------|--------|-------------|
|1014       |FNHLK      |987     |  1          |
|-----------|-----------|--------|-------------|
|3371       |FNHPO      |987     |  2          |
|-----------|-----------|--------|-------------|
|990        |FNAAA      |3371    |  1          |
|--------------------------------|-------------|

级别

  1. branchidparentid相同且branchtypeid为2的branchcode是第一个parent分支。
  2. A branchcodebranchidparentid 相同但 branchtypeid 是 2是第二个 parent 分支,否则是 child 分支。

  3. Child 分支应按照其 parent 分支的排序方式进行排序。

需要输出

|--------------------------------|-------------| |branchid |branchcode |parentid|branchtypeid | |-----------------------|--------|-------------| |438 |UKHQR |438 | 2 | |-----------|-----------|--------|-------------| |987 |FNOLR |987 | 2 | |-----------|-----------|--------|-------------| |3683 |UKSNL |438 | 2 | |-----------|-----------|--------|-------------| |3371 |FNHPO |987 | 2 | |-----------|-----------|--------|-------------| |539 |UKBRS |438 | 1 | |-----------|-----------|--------|-------------| |3110 |UKNNX |3683 | 1 | |-----------|-----------|--------|-------------| |1014 |FNHLK |987 | 1 | |-----------|-----------|--------|-------------| |990 |FNAAA |3371 | 1 | |--------------------------------|-------------|

我已经做过的事情:

SELECT branchcode,branchid,parentid
   FROM branches
      START WITH parentid IN ( SELECT parentid FROM branches where parentid = branchid)
      CONNECT BY NOCYCLE PRIOR  parentid = branchid
     ORDER SIBLINGS BY parentid;

您的代码的主要问题 - 假设您想要返回所有级别的数据 - 是您只获得具有顶级父级的行 - 即级别 1 和 2。那是因为您的 start with子句正在寻找任何父 ID;然后您的 connect by 正在以错误的方式搜索。所以你查询得到六行:

BRANCHCODE   BRANCHID   PARENTID
---------- ---------- ----------
UKHQR             438        438
UKBRS             539        438
UKSNL            3683        438
FNOLR             987        987
FNHLK            1014        987
FNHPO            3371        987

.. 都带有两个原始顶级 ID 之一,438 或 987。

如果你修复这些问题,首先获取两个真正的顶级父级(而不是使用子查询)然后反转连接方式:

SELECT branchcode, branchid, parentid
FROM branches
START WITH parentid = branchid
CONNECT BY NOCYCLE parentid = PRIOR branchid
ORDER SIBLINGS BY parentid;

BRANCHCODE   BRANCHID   PARENTID
---------- ---------- ----------
UKHQR             438        438
UKBRS             539        438
UKSNL            3683        438
UKNNX            3110       3683
FNOLR             987        987
FNHLK            1014        987
FNHPO            3371        987
FNAAA             990       3371

...您将以更正常的顺序获得所有 8 行。顺便说一下, nocycle 只是因为定义顶级的方式而需要;根据我的经验,根元素父 ID 为空更为常见。无论如何,另一种避免循环的方法是:

CONNECT BY parentid = PRIOR branchid AND branchid != PRIOR parentid

但我离题了。您可以添加更多信息,包括层次结构的缩进视图:

SELECT branchcode, branchid, parentid,
  lpad(' ', level - 1, ' ') || branchcode as nestedbranch
FROM branches
START WITH parentid = branchid
CONNECT BY NOCYCLE parentid = PRIOR branchid
ORDER SIBLINGS BY parentid;

BRANCHCODE   BRANCHID   PARENTID NESTEDBRANCH   
---------- ---------- ---------- ---------------
UKHQR             438        438 UKHQR          
UKBRS             539        438  UKBRS         
UKSNL            3683        438  UKSNL         
UKNNX            3110       3683   UKNNX        
FNOLR             987        987 FNOLR          
FNHLK            1014        987  FNHLK         
FNHPO            3371        987  FNHPO         
FNAAA             990       3371   FNAAA        

但是您说您希望所有父项都位于顶部,这有点奇怪,并且让既是父项又是子项的行处于不确定状态。您可以通过在排序中使用 case 表达式来实现这一点,可能包括上下文的根元素(以及有用的级别),例如:

SELECT branchcode, branchid, parentid,
  CONNECT_BY_ROOT(branchcode) AS rootbranch,
  lpad(' ', level - 1, ' ') || branchcode as nestedbranch
FROM branches
START WITH parentid = branchid
CONNECT BY NOCYCLE parentid = PRIOR branchid
ORDER BY CASE WHEN branchid = parentid THEN 1 ELSE 2 END, -- puts all parents first
  CONNECT_BY_ROOT(branchid), level, branchcode;

BRANCHCODE   BRANCHID   PARENTID ROOTBRANCH NESTEDBRANCH   
---------- ---------- ---------- ---------- ---------------
UKHQR             438        438 UKHQR      UKHQR          
FNOLR             987        987 FNOLR      FNOLR          
UKBRS             539        438 UKHQR       UKBRS         
UKSNL            3683        438 UKHQR       UKSNL         
UKNNX            3110       3683 UKHQR        UKNNX        
FNHLK            1014        987 FNOLR       FNHLK         
FNHPO            3371        987 FNOLR       FNHPO         
FNAAA             990       3371 FNOLR        FNAAA        

但这似乎仍然不是很有用...所以也许您真的想让每个父项都在其子项之前,而较早的查询确实如此。

db<>fiddle