我刚开始使用OPENJSON
SQL Server 2016 SP1。
我有这样一句话:
select c.Serial as Parent,
(Select co.Serial, agc.Position
from AggregationChildren agc, Aggregation ag, Code co
where agc.AggregationId = a.AggregationId
and co.CodeId = agc.AggregationChildrenId for json path) as children
from Aggregation a, Code c
where c.CodeId = a.AggregationId for json path
要生成此 JSON:
{"Parent":"4244287599479491","Children":
[{"Serial":"8915753733724633","Position":"1"},
{"Serial":"1247782815710855","Position":"2"},
...]}
但它非常非常慢。
我的问题是Children
数组,因为我不知道如何获取它。
有没有办法做得更快?
这些是表格:
CREATE TABLE [dbo].[Code] (
[CodeId] INT IDENTITY (1, 1) NOT NULL,
[Serial] NVARCHAR (20) NOT NULL,
[ ... ],
CONSTRAINT [PK_CODE] PRIMARY KEY CLUSTERED ([CodeId] ASC),
[ ... ]
)
CREATE TABLE [dbo].[Aggregation] (
[AggregationId] INT NOT NULL,
[ ... ],
CONSTRAINT [PK_AGGREGATIONS] PRIMARY KEY CLUSTERED ([AggregationId] ASC),
CONSTRAINT [FK_Aggregation_Code]
FOREIGN KEY ([AggregationId])
REFERENCES [dbo].[Code] ([CodeId])
)
CREATE TABLE [dbo].[AggregationChildren] (
[AggregationChildrenId] INT NOT NULL,
[AggregationId] INT NOT NULL,
[Position] INT NOT NULL,
CONSTRAINT [PK_AGGREGATION_CHILDS] PRIMARY KEY CLUSTERED ([AggregationChildrenId] ASC),
CONSTRAINT [FK_AggregationChildren_Code]
FOREIGN KEY ([AggregationChildrenId])
REFERENCES [dbo].[Code] ([CodeId]),
CONSTRAINT [FK_AggregationChildren_Aggregation]
FOREIGN KEY ([AggregationId])
REFERENCES [dbo].[Aggregation] ([AggregationId]) ON DELETE CASCADE
)
该Serial
列是一个,nvarchar(20)
因为值可以是字母数字的任意组合,即使我的示例只显示数字。
我很难解析您的查询,但我相信这会返回相同的结果,而且速度要快得多:
上述查询的计划如下所示:
您的查询计划如下所示:
如果我们添加以下索引,我们可以使第一个变体更快:
但是,显然,您需要根据您的工作量对此进行评估。
我创建了一个最低限度可行的完整示例设置以用于测试:
我重新格式化了约束条款,使其更适合我的大脑;本质上,上面的代码与您问题中的 DDL 相同。
这会用足够的数据填充三个表以进行有意义的比较:
这些是每个表的行数:
我的查询版本:
为了比较两个查询的输出,我创建了两个用户定义的函数,如下所示:
现在,我可以通过以下方式比较两个查询的输出:
结果是:
结果不匹配。我查询的输出包含的子节点少于您的查询。我要回到绘图板,并将简化测试平台以查看差异所在。
简化的测试床由表中的 10 行、(父)表
Code
中的 2 行和(子)表中的 8 行组成:Aggregation
AggregationChildren
行数:
预测的模式应该是两个父 json 数组,每个都有 4 个子数组。
我的结果:
您的查询:
您的查询有太多孩子;我的查询返回了预测的孩子数量,它返回了正确的
Position
值,但是返回了不正确的Serial
值。我查询中的“错误”出现在内部查询中。不正确的查询是:
正确的版本是:
更正后的查询现在看起来像:
并返回以下结果: