【问题标题】:JOOQ Query hierarchyJOOQ 查询层次结构
【发布时间】:2019-05-02 04:31:49
【问题描述】:

我对表调用“menu”有疑问。此表使用 pid null 保存父菜单项,使用 pid = "parent id" 保存子菜单项。

表结构为:

CREATE TABLE security.menu (
  id UUID NOT NULL,
  pid UUID DEFAULT NULL,
  url VARCHAR(100) DEFAULT NULL,
  name VARCHAR(50)DEFAULT NULL,
  seq NUMERIC DEFAULT NULL,
  state NUMERIC DEFAULT 1,
  created_at TIMESTAMP DEFAULT NULL,
  updated_at TIMESTAMP DEFAULT NULL,
  PRIMARY KEY (id)
);

而数据是:

我需要构建一个 JOOQ 查询以使用字段 seqidpid 以树模式检索数据。

我需要帮助才能得到查询结果:

-Menu 1
     -Sub Menu 1
-Menu 2
-Menu 3
-Menu 1

上面的预期结果考虑了seq字段和字段pid

【问题讨论】:

  • 您好,最好将您尝试过的内容张贴出来,以便人们可以从那里帮助您。展示一些代码示例,让社区更好地帮助您!
  • 您的seq 内容真的正确吗?为什么Menu 1Menu 2 具有相同的seq 值?我假设seq 用于在任何给定菜单项的子项中订购兄弟姐妹...
  • @LukasEder,菜单 2 的 seq 错误,抱歉。
  • @MG_Bautista:不用担心 :) 也许你应该添加一个 UNIQUE (pid, seq) 键!

标签: java sql postgresql jooq


【解决方案1】:

用 SQL 来做

对于我的回答,我将假设 seq 用于在您的菜单层次结构中订购兄弟姐妹,并且您的示例数据是错误的(没有两个兄弟姐妹可能具有相同的 seq 值,即应该是UNIQUE (pid, seq)。所以,我将使用这个示例数据(为简单起见,INT IDs):

INSERT INTO menu (id, pid, name, seq)
VALUES 
  (1, null, 'Menu 1', 1), 
  (2, null, 'Menu 2', 2), 
  (3, null, 'Menu 3', 3), 
  (4, 1, 'Sub Menu 1', 1), 
  (5, null, 'Menu 1', 9);

您将需要使用WITH clause 进行递归查询。在 SQL 中:

WITH RECURSIVE m AS (
  SELECT 
    id, 
    ARRAY[seq] AS path, 
    name, 1 AS level, 
    '- ' || name AS display
  FROM menu
  WHERE pid IS NULL
  UNION ALL 
  SELECT 
    menu.id, 
    path || seq, 
    menu.name, 
    m.level + 1 AS level, 
    repeat('  ', m.level) || '- ' || menu.name
  FROM menu JOIN m ON m.id = menu.pid
)
SELECT *
FROM m
ORDER BY path;

The query output can be seen here。它是:

id |path  |name       |level |display        |
---|------|-----------|------|---------------|
1  |{1}   |Menu 1     |1     |- Menu 1       |
4  |{1,1} |Sub Menu 1 |2     |  - Sub Menu 1 |
2  |{2}   |Menu 2     |1     |- Menu 2       |
3  |{3}   |Menu 3     |1     |- Menu 3       |
5  |{9}   |Menu 1     |1     |- Menu 1       |

当然,还有其他方法可以达到相同的效果。栏目说明:

  • id:原菜单项id
  • path:通向任何给定菜单项的路径(连接的 seq 值数组,假设它们在 pid 中是唯一的)
  • name:菜单项的原始名称
  • level:递归或嵌套级别(用于填充)
  • display:菜单项的填充显示,根据您的问题

用 jOOQ 来做

现在,您只需将上述内容转换为 jOOQ 查询即可。

假设这些静态导入(一如既往):

import static org.jooq.impl.DSL.*;
import static com.example.generated.Table.*;

如下:

Field<Integer[]> path = array(MENU.SEQ).as("path");
Field<Integer> level = inline(1).as("level");
Field<String> display = inline("- ").concat(MENU.NAME).as("display");

Table<?> m = name("m").as(
  select(MENU.ID, path, MENU.NAME, level, display)
 .from(MENU)
 .where(MENU.PID.isNull())
 .unionAll(
  select(
    MENU.ID,
    PostgresDSL.arrayAppend(path, MENU.SEQ),
    MENU.NAME,
    level.add(inline(1)),
    repeat(inline("  "), level).concat(inline("- ")).concat(MENU.NAME))
 .from(MENU)
 .join(table(name("m"))).on(field(name("m", "id"), Integer.class).eq(MENU.PID)))
);

ctx.selectFrom(m).orderBy(path).fetch();

【讨论】:

    猜你喜欢
    • 2020-04-17
    • 2015-10-15
    • 1970-01-01
    • 2016-01-06
    • 2012-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多