从 JSON 中查找祖先

Mic*_*een 5 sql-server t-sql json

我有一个看起来像这样的层次结构:

在此处输入图片说明

作为 TSQL 中的 JSON,它是这样的:

declare @Employees nvarchar(max) =
'{
  "person": "Amy",
  "staff": [
    { "person": "Bill" },
    {
      "person": "Chris",
      "staff": [
        { "person": "Dan" },
        { "person": "Emma" }
      ]
    }
  ]
}';
Run Code Online (Sandbox Code Playgroud)

这只是一个例子。实际数据可以是任何深度或广度不确定的树。

发现文档和所有示例都显示了自上而下的遍历。每个 JSON 路径都从根节点开始,并通过已知的节点名称导航到所需的节点。我没有发现从层次结构中的不确定深度开始并向上工作。我觉得我需要像传递闭包这样的东西。

给定一个名字,我想获得该名字的血统。例如,给定“Emma”,结果将是“Emma / Chris / Amy”。给定“比尔”,答案将是“比尔/艾米”。输出格式不重要;它可以是 JSON、字符串或结果集。名字是独一无二的。

这是对我自己的学习练习。只要它仍然是 JSONy,就可以将原始 JSON 表示更改为任何等效的内容。层次结构的邻接列表表示上的 JSON_QUERY 无法实现我的目标。

Pet*_*ier 7

在我看来,这是一个非常普通的递归查询,只要您动态地解开 JSON。

如果HandyD会原谅一些轻微的抄袭......

declare @Employees nvarchar(max) =
'{
  "person": "Amy",
  "staff": [
    { "person": "Bill" },
    {
      "person": "Chris",
      "staff": [
        { "person": "Dan" },
        { "person": "Emma" }
      ]
    }
  ]
}';

;WITH hier ([Level], Parent, Person, staff) AS (
    SELECT 
        1 AS [Level], 
        convert(nvarchar(255),'') AS Parent, 
        l1.person, 
        l1.staff
    FROM OPENJSON(@Employees) WITH (
        person NVARCHAR(255),
        staff NVARCHAR(MAX) AS JSON
    ) l1
UNION ALL 
    select 
        [Level]+1,
        convert(nvarchar(255),h.Person) as Parent,
        oj.person,
        oj.staff
    from hier h 
    outer apply openjson(h.staff) with (
        person NVARCHAR(255),
        staff NVARCHAR(MAX) AS JSON
    ) oj
    where [Level] < 100 -- or relevant maxrecursion level
        and oj.Person is not null
)
SELECT 
    [Level], 
    Parent, 
    Person 
FROM hier
order by [Level];
Run Code Online (Sandbox Code Playgroud)