Oracle_ROW_NUMBER 用于分页层级查询

Oracle_ ROW_NUMBER for paging hierarchy query

这次我遇到一个问题,就是层级的分页查询table。

table_name(id varchar2(50), id_parent varchar2(50) );

所以对于示例数据,我有:

WITH table_name AS
(
    SELECT '3' id, '' id_parent FROM DUAL UNION ALL
    SELECT '5' id, '3' id_parent FROM DUAL UNION ALL
    SELECT 's' id, '3' id_parent FROM DUAL UNION ALL
    SELECT '4' id, 'as' id_parent FROM DUAL UNION ALL
    SELECT 'aa' id, 'as' id_parent FROM DUAL UNION ALL
    SELECT 'as' id, '3' id_parent FROM DUAL UNION ALL
    SELECT 'ad' id, '3' id_parent FROM DUAL UNION ALL
    SELECT '2' id, '' id_parent FROM DUAL 
)
SELECT LPAD('-', 2 * (level - 1), '-') || id AS id1,
    id_parent, 
    rownum  --Seem not legit here
FROM table_name
START WITH id_parent IS NULL
CONNECT BY PRIOR id = id_parent 
--ORDER SIBLINGS BY id
;

这是预期的输出:

id          id_parent   rownum
2                       1
3                       2
--5         3           3
--ad        3           4
--as        3           5
----4       as          6
----aa      as          7
--s         3           8

现在我指望 rownum 为 row_number 进行分页。作为 Oracle 层次结构查询的文档,这确保我可以将树显示为我们想要的预排序遍历,但通常 SQL,IMO 它不保证相同级别的节点将被排序(或不?)。

所以我需要 ROW_NUMBER() OVER (ORDER SIBLINGS BY id) 这样的东西。但是我没有找到类似的东西。

有什么方法可以解决这个问题吗?

先排序,然后使用子查询生成 ROWNUM

SELECT t.*,
       ROWNUM
FROM   (
  SELECT LPAD('-', 2 * (level - 1), '-') || id AS id1,
      id_parent
  FROM table_name
  START WITH id_parent IS NULL
  CONNECT BY PRIOR id = id_parent 
  ORDER SIBLINGS BY id
) t;

您需要外部查询,因为查询中的执行顺序是:

  • 行被选中;
  • 然后应用 WHERE 子句过滤器(并且 ROWNUM 伪列是 为匹配所有 WHERE 子句过滤器的每一行生成 - 在这种情况下没有 WHERE 子句,因此所有行都将被编号);
  • 然后应用 ORDER BY 子句。

在单个查询中应用此方法将获取在数据库中找到的行,然后为它们提供行号,最后对这些行进行排序(不是您想要的)。使用内部查询,您可以强制首先应用 ORDER BY 子句,然后在执行外部查询时生成行号。