编写一个查询,该查询将所有父级放在首位,然后返回孩子

时间:2019-08-19 14:39:25

标签: sql oracle oracle11g hierarchical-data

表结构:

|--------------------------------|-------------|
|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. 一个branchcodebranchid相同且parentid为2的branchtypeid是第一个父分支。
  2. 一个branchcodebranchid 相同但parentid为2的branchtypeid是第二个父分支,否则这是一个子分支。

  3. 子分支应该按照其父分支的排序方式进行排序。

必需的输出

|--------------------------------|-------------| |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 个答案:

答案 0 :(得分:0)

您的代码的主要问题-假设您希望返回所有级别的数据-您只获得具有顶级父级的行(即级别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为null更常见。无论如何,避免该循环的另一种方法是:

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