typeorm的递归查询怎么写?

如果这个表数据是这样的,怎么通过查找id然后递归出来pid?

image.png

阅读 3.3k
3 个回答

oracle用connect by,start with语法
mysql写存储过程或者java代码里面一层一层向上级节点查,如果表数据量不大可以直接查全表数据,内存中处理

数据库新手,来讨论下 SQL

这个可以用 (Recursive) CTE (递归公共表表达式) 实现。连 SQLite 都支持:

查询

  • 'f' 自身及所有父节点

结果

result
f -> c -> a

SQLite 实现

WITH RECURSIVE
  
  query(msg) AS (
    VALUES ('f')
  ),

  data(id, msg, pid) AS (
    VALUES
      (1, 'a', NULL),
      (2, 'b', NULL),
      (3, 'c', 1),
      (4, 'd', 1),
      (5, 'e', 3),
      (6, 'f', 3)
  ),
  
  parents(msg, pid) AS (
    SELECT data.msg, data.pid
      FROM query q
      JOIN data ON q.msg = data.msg
     UNION ALL
    SELECT data.msg, data.pid
      FROM parents self
      JOIN data ON self.pid = data.id
     WHERE self.pid IS NOT NULL
  )

SELECT group_concat(msg, ' -> ')
  FROM parents;

首先typeorm肯定是没有专门方法用于递归查询的,所以只能是原始SQL语句去做这个。

typeorm最新的文档里没有这种纯粹原始SQL的查询方式,不太确定这个版本还能不能这样用,不过以前是这么用的:

await db.entityManager.query("select ... where id=?", [id])

另外,看你标签是mysql,首先确定是MySQL 8.0以上支持CTE,也就是with recursive 语句。

8.0+

支持CTE的话就好办了

with recursive cte (id, msg, pid) as (
  select     id,
             msg,
             pid
  from       products
  where      id = ?
  union all
  select     p.id,
             p.msg,
             p.pid
  from       products p
  inner join cte
          on p.id = cte.pid
)
select * from cte;

5.x

不支持CTE的话,也有很多办法可以实现,比如存储过程等方式,不过都不太可能一次查询就方便做到,所以效率是个问题。

如果递归层级不深,只有2,3层的话,可以硬写,有几层就left join这个table本身几次。或者全查出来之后,在代码层面查找。这个主要看具体情况了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题