【问题标题】:cte sql to simple subset query for JPActe sql 到 JPA 的简单子集查询
【发布时间】:2019-07-20 05:35:29
【问题描述】:

我们如何将下面的 CTE 查询(递归)更改为简单的子集 sql:

  WITH links (parent, child) AS
  ( SELECT parent, child
        FROM Heirarchy_Table
        WHERE parent = '111111'
   UNION ALL 
    SELECT ht.parent, ht.child
        FROM Heirarchy_Table ht
        INNER JOIN links ON links.child = ht.parent)
SELECT * FROM links fl;

我需要将此查询用于 JPA,因为 JPA 未处理“WITH”子句。 [注意:“链接”cte 是递归使用的]。 非常感谢!!

【问题讨论】:

  • 谢谢肖恩,但我知道 JPA 没有处理“WITH”子句。此外,在上面的查询中,我们使用递归。所以,SELECT * from (SELECT * ...) 对我不起作用。
  • 不做递归就不能做递归。因此,将其移至子查询或任何不起作用的东西。处理这个问题的最好方法是创建一个存储过程并从 JPA 中调用它。
  • 是的,有道理。我试图避免存储过程。但是,这看起来是一个不错的解决方法。非常感谢!!

标签: sql sql-server spring-boot jpa spring-data-jpa


【解决方案1】:

我们如何将下面的 CTE 查询(递归)更改为简单的子集 sql:

创建一个视图。

create view links
as
WITH links (parent, child) AS
( SELECT parent, child
    FROM Heirarchy_Table
    WHERE parent = '111111'
UNION ALL 
SELECT ht.parent, ht.child
    FROM Heirarchy_Table ht
    INNER JOIN links ON links.child = ht.parent)
SELECT * FROM links fl;

然后就可以查询视图了

select * from links

或者您可以使用内联表值函数,有时称为“参数化视图”,如下所示:

create or alter function GetLinks(@parent int)
returns table
as 
return
WITH links (parent, child) AS
(SELECT parent, child
    FROM Heirarchy_Table
    WHERE parent = @parent
UNION ALL 
SELECT ht.parent, ht.child
    FROM Heirarchy_Table ht
    INNER JOIN links ON links.child = ht.parent)
SELECT * FROM links fl;

你可以像这样查询:

select * from GetLinks(1111)

【讨论】:

  • 这里,“WHERE parent = '111111'”在运行时获得价值,这也在 CTE 内部。所以,我认为,视图不是一个好的选择。
  • 谢谢大卫。这看起来是个不错的选择。我不知道 MsSql 中有这个功能。
【解决方案2】:
@Query(value = "WITH RECURSIVE domainCTE AS (" +
        "   SELECT *, " +
        "       id AS root " +
        "       FROM domain " +
        "       WHERE parent IS NULL " +
        "   UNION ALL " +
        "       SELECT domain.*, " +
        "           domainCTE.root " +
        "       FROM domain " +
        "       JOIN domainCTE ON domain.parent = domainCTE.id " +
        ") " +
        "SELECT DISTINCT d.id, d.name, d.parent FROM domain d " +
        "    JOIN domainCTE cte " +
        "    ON d.id = cte.root " +
        "    WHERE cte.id IN :domainIds",
        nativeQuery = true
)
List<Domain> findDomainRootsByDomainIds(List<Long> domainIds);

【讨论】:

  • 欢迎来到 SO。请在代码中添加相关描述,以更好地理解您的答案。 SO 不推荐纯代码答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多