Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 具有特定起点和内部联接的cte递归查询_Sql Server_Sql Server 2008_Tsql_Jdbctemplate - Fatal编程技术网

Sql server 具有特定起点和内部联接的cte递归查询

Sql server 具有特定起点和内部联接的cte递归查询,sql-server,sql-server-2008,tsql,jdbctemplate,Sql Server,Sql Server 2008,Tsql,Jdbctemplate,假设我有以下模式: person (person_id, person_account, name) relationships (person_id, father_id) purchases(person_account, total, type) 免责声明:我没有设计这个模式,我知道这很糟糕,所以我道歉。这也是一个例子,这要复杂得多。还要注意,这是我将在JDBCTemplate中使用的查询,这就是我包含标记的原因 现在我想计算一个人的购买量,他或她的儿子购买,他们的儿子购买等等。我想要一

假设我有以下模式:

person (person_id, person_account, name)
relationships (person_id, father_id)
purchases(person_account, total, type)
免责声明:我没有设计这个模式,我知道这很糟糕,所以我道歉。这也是一个例子,这要复杂得多。还要注意,这是我将在JDBCTemplate中使用的查询,这就是我包含标记的原因

现在我想计算一个人的购买量,他或她的儿子购买,他们的儿子购买等等。我想要一个关于最初的人的特定起点

与我目前看到的示例不同的是:

  • 一个特定的起点(假设它是
    个人账户
  • purchases
    没有
    person\u id
    字段,因此使事情复杂化
  • 我要的是
    计数
    ,而不是其他东西
  • 我想按
    购买
    类型
    进行筛选
  • 由于父id关系位于另一个表中,这意味着必须进行连接。同样,这很可怕,但我无法更改数据库以在
    person
    表中包含
    father\u id
    字段
  • 如果一个人没有父亲,则
    关系表中没有条目。这将使情况更加复杂
  • 现在我已经阅读了这些示例,并理解了其中的几个:


    然而,我在理解起点和终点方面存在问题。我的起点可以有一个父亲,所以不能为空。我的端点应该从在
    关系表中没有条目的人那里获得
    购买

    所以我想的是:

    declare @id int = 234 
    
    ;with CTEexample as (
         select p.person_account, p.person_id, p.type, r.father_id from purchases as s
             join person p on p.person_account = s.person_account
             join relationships r on r.person_id = p.person_id
             where r.person_id = @id
         union all
         select p.person_account, p.person_id, p.type, r_father_id from purchases as s
             join person p on p.person_account = s.person_account
             join relationships r on r.person_id = p.person_id
             join CTEexample c on p.person_id = r.father_id
     )
     select count(*) from CTEexample
          where type = 's'
    
    然而,它根本不起作用

    任何帮助都将不胜感激。

    保持递归简单(其他人更容易管理),并使用它获取关系。从那里,您可以加入到Person以获得帐号,然后购买

    DECLARE @PersonID INT = 1
    
    ;WITH Family (PersonID, FatherID) AS (
      SELECT p.PersonID, null
      FROM Person p
      WHERE p.PersonID = @PersonID
    
      UNION ALL
    
      SELECT p.PersonID, r.FatherID
      FROM Person p
      INNER JOIN Relationships r
        ON r.PersonID = p.PersonID -- Me
      INNER JOIN Family f
        ON f.PersonID = r.FatherID -- Father
    )
    SELECT *
    FROM Family f
    JOIN Person p
      ON p.PersonID = f.PersonID
    JOIN Purchases ps
      ON ps.PersonAccount = p.PersonAccount
    WHERE ps.Type is null
    

    您有一个非常详细的问题,但我猜您在递归CTE中的谓词正在造成严重破坏。通常,您需要通过递归和查找树来做两件重要的事情:

  • 您需要知道您处于“位置”的级别(在我的示例中为pos)
  • 您需要根据递归中的位置确定关系,以使递归有意义。否则,您将再次显示相同的值,而不会真正使用它所能做的递归功能
  • 以下是一个可能适用于您的示例:

  • 会给你一个层次结构
  • 将找到树的最远横档(最低位置)
  • 将后代和子代的顺序添加到一起
  • 递归的最大好处不是一个或两个级别,而是当您达到5个或更多级别时,能够告诉表达式您想要它的哪一部分。当我做递归时,我通常做两个cte,一个做递归,另一个求最大递归,然后告诉我。否则,每个人都会带着不同等级的继承权回来。除非你真的想要,否则你应该用一个窗口表达式来限制它

    我希望这会有所帮助,有时您必须为自己的情况定制一段时间的递归CTE:

    Declare @table table ( PersonId int identity, PersonName varchar(512), Account int, ParentId int, Orders int);
    
    insert into @Table values ('Brett', 1, NULL, 1000),('John', 1, 1, 100),('James', 1, 1, 200),('Beth', 1, 2, 300),('John2', 2, 4, 400);
    
    select 
        PersonID
    ,   PersonName
    ,   Account
    ,   ParentID
    from @Table
    
    ; with recursion as 
        (
        select 
            t1.PersonID
        ,   t1.PersonName
        ,   t1.Account
        --, t1.ParentID
        ,   cast(isnull(t2.PersonName, '')
                + Case when t2.PersonName is not null then '\' + t1.PersonName else t1.PersonName end
                as varchar(255)) as fullheirarchy
        ,   1 as pos
        ,   cast(t1.orders + 
                isnull(t2.orders,0) -- if the parent has no orders than zero
                as int) as Orders
        from @Table t1
            left join @Table t2 on t1.ParentId = t2.PersonId
        union all
        select 
            t.PersonID
        ,   t.PersonName
        ,   t.Account
        --, t.ParentID
        ,   cast(r.fullheirarchy + '\' + t.PersonName as varchar(255))
        ,   pos + 1  -- increases
        ,   r.orders + t.orders
        from @Table t
            join recursion r on t.ParentId = r.PersonId
        )
    , b as 
        (
        select *, max(pos) over(partition by PersonID) as maxrec  -- I find the maximum occurrence of position by person
        from recursion
        )
    select *
    from b
    where pos = maxrec  -- finds the furthest down tree
    -- and Account = 2  -- I could find just someone from a different department
    

    不确定,但尝试反向加入CTEexample。因此,在p.person\u id=r.father\u id上加入CTEexample c成为在r.person\u id=p.father\u id上加入CTEexample c