Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.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 如何使用Microsoft SQL Server 2016生成分层JSON数据?_Sql Server_Json - Fatal编程技术网

Sql server 如何使用Microsoft SQL Server 2016生成分层JSON数据?

Sql server 如何使用Microsoft SQL Server 2016生成分层JSON数据?,sql-server,json,Sql Server,Json,我正在使用Microsoft SQL Server 2016。此版本支持JSON 我有一个包含以下数据的个人表: 拟人 慈父 名称 1. 无效的 第四祖父 2. 1. 三公 3. 2. 二公 4. 3. 祖父 5. 4. 父亲 6. 4. 叔叔 7. 6. 表妹 8. 5. 兄弟 9 5. 我 不幸的是,递归CTe不能用于生成分层json。递归CTE的输出仍然是平坦的结果 创建分层输出的唯一方法是为每个级别创建单独的CTE,然后加入using for JSON AUTO 准备表格: declar

我正在使用Microsoft SQL Server 2016。此版本支持JSON

我有一个包含以下数据的个人表:

拟人 慈父 名称 1. 无效的 第四祖父 2. 1. 三公 3. 2. 二公 4. 3. 祖父 5. 4. 父亲 6. 4. 叔叔 7. 6. 表妹 8. 5. 兄弟 9 5. 我
不幸的是,递归CTe不能用于生成分层json。递归CTE的输出仍然是平坦的结果

创建分层输出的唯一方法是为每个级别创建单独的CTE,然后加入using for JSON AUTO

准备表格:

declare @t table (PersonId int, FatherId int, Name nvarchar(20));

insert into @t(PersonId, FatherId, Name)
values
(1, NULL, '4th Grand Father'),
(2, 1, '3rd Grand Father'),
(3, 2, '2nd Grand Father'),
(4, 3, 'Grand Father'),
(5, 4, 'Father'),
(6, 4, 'Uncle'),
(7, 6, 'Cousin'),
(8, 5, 'Brother'),
(9, 5, 'Me');
--分层查询:

WITH
Persons_CTE1 AS(
    SELECT PersonId, FatherId, Name FROM @t WHERE FatherId IS NULL
),
Persons_CTE2 AS(
    SELECT P.PersonId, P.FatherId, P.Name
    from @t P
    WHERE P.FatherId IN (SELECT PersonId FROM Persons_CTE1)
),
Persons_CTE3 AS(
    SELECT P.PersonId, P.FatherId, P.Name
    from @t P
    WHERE P.FatherId IN (SELECT PersonId FROM Persons_CTE2)
),
Persons_CTE4 AS(
    SELECT P.PersonId, P.FatherId, P.Name
    from @t P
    WHERE P.FatherId IN (SELECT PersonId FROM Persons_CTE3)
),
Persons_CTE5 AS(
    SELECT P.PersonId, P.FatherId, P.Name
    from @t P
    WHERE P.FatherId IN (SELECT PersonId FROM Persons_CTE4)
),
Persons_CTE6 AS(
    SELECT P.PersonId, P.FatherId, P.Name
    from @t P
    WHERE P.FatherId IN (SELECT PersonId FROM Persons_CTE5)
)
select Persons_CTE1.Name, Persons_CTE2.Name, Persons_CTE3.Name,
       Persons_CTE4.Name, Persons_CTE5.Name, Persons_CTE6.Name
from Persons_CTE1
    LEFT JOIN Persons_CTE2
        ON Persons_CTE2.FatherId = Persons_CTE1.PersonId
    LEFT JOIN Persons_CTE3
        ON Persons_CTE3.FatherId = Persons_CTE2.PersonId
    LEFT JOIN Persons_CTE4
        ON Persons_CTE4.FatherId = Persons_CTE3.PersonId
    LEFT JOIN Persons_CTE5
        ON Persons_CTE5.FatherId = Persons_CTE4.PersonId
    LEFT JOIN Persons_CTE6
        ON Persons_CTE6.FatherId = Persons_CTE5.PersonId
FOR JSON AUTO

当然,使用递归CTE实现Json树非常困难(如果不是不可能的话)

但是,使用递归函数确实很有帮助,可以解决问题: 去

值得一提的是,如果其内部对象无效,则无法构建函数。因此,有必要将功能构建为:

CREATE FUNCTION fn_Json(@PersonId INT, @IsRoot INT) 
RETURNS VARCHAR(MAX)
BEGIN 
   RETURN 1
END 
然后使用fist代码。如果要将根节点包括在内,请设置

@IsRoot = 1

如果不是
@IsRoot=2
或其他一些值

就没有办法为每个级别动态执行CTE?您必须在查询中预期6个级别,对吗?比如说如果有7个级别呢?阿夫辛·阿米里:请原谅我的无知,但是在你的例子中,你会如何调用这个函数?我也有类似的需求,我正在尝试使用你的功能,但不是为我工作。我肯定我做错了,如果您使用的是SQL Server,请使用“select fn_Json(@PersonId INT,@IsRoot INT)”并替换参数
@IsRoot = 1