You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL查询输出层级化JSON的最优实现方案

SQL查询输出层级JSON性能优化问题

我在尝试将SQL查询结果输出为符合要求的JSON格式时遇到了问题。原始查询仅涉及两张表,使用FOR JSON Auto只会返回扁平化的对象数组,实际数据存在层级关系:Q2CNum -> LineItems -> Identifier。
我尝试过使用FOR JSON Path,但它仅能对单个JSON对象做结构调整,无法将所有Identifier聚合到所属的父级LineItem下。
之后我通过新增自连接的方式调整查询,FOR JSON Path Auto可以输出更符合要求的结构,但查询耗时从2秒飙升到20秒,性能下降严重,我猜测是自连接写法不合理或者多表连接的效率过低导致的,我无法公开更多业务细节,希望能获得可行的优化方案。

更新1

当前基础查询执行后只能得到扁平化JSON(仅为对象数组),查询代码如下:

Select OWS.Q2CNum, 
       OWS.LineItem, 
       OWS.Identifier, 
       OWS.ProductType, 
       OWS.Workstation, 
       OWS.Calculation, 
       OWS.UnitOfMeasure, 
       OWS.CurrentStatus, 
       LS.Location, 
       LS.ProgramStamp_LocalTime
FROM table1 AS OWS
INNER JOIN table2 AS LS
ON OWS.Q2CNum = LS.[Order]
AND OWS.LineItem = LS.LineItem
AND OWS.Identifier = LS.Identifier
WHERE LS.ProgramStamp_LocalTime = 
    (Select TOP 1 LS2.ProgramStamp_LocalTime
    from dbo.view_Location_Stamps_Local AS LS2 
    Where LS2.[Order] = OWS.Q2CNum
    AND LS2.LineItem= OWS.LineItem
    AND LS2.Identifier = OWS.Identifier
    Order by LS2.ProgramStamp_LocalTime Desc) 
AND LS.[Order] = @testVar
AND LS.LineItem = COALESCE('001',OWS.LineItem)
AND LS.Identifier like '%'
---Group by Q2CNum
ORDER BY Q2CNum, LineItem, Identifier DESC
FOR JSON Auto

我需要的目标层级JSON结构如下:

{
    "Q2CNum": "value",
    "LineItems": [{
         "LineItem": "value",
         "Identifiers": [{
               "identifier": "value",
               "etc": "..."
         }]
    }]
}

更新2

调整后的查询可以输出更接近需求的结果,但耗时更长,代码如下:

Select Q2C.Q2CNum, 
       Li.LineItem  , 
       OWS.Identifier, 
       OWS.ProductType, 
       OWS.Workstation, 
       OWS.Calculation, 
       OWS.UnitOfMeasure, 
       OWS.CurrentStatus, 
       LS.Location, 
       LS.ProgramStamp_LocalTime
FROM table1 AS OWS
INNER JOIN table2 AS Q2C
ON Q2C.Q2CNum = OWS.Q2CNum and Q2C.LineItem = OWS.LineItem and Q2C.Identifier = OWS.Identifier and Q2C.Workstation = OWS.Workstation
INNER JOIN table3 AS Li
ON Li.Q2CNum = OWS.Q2CNum and Li.LineItem = OWS.LineItem and Li.Identifier = OWS.Identifier and Li.Workstation = OWS.Workstation
INNER JOIN table4 AS LS
ON OWS.Q2CNum = LS.[Order]
AND OWS.LineItem = LS.LineItem
AND OWS.Identifier = LS.Identifier
WHERE LS.ProgramStamp_LocalTime = 
    (Select TOP 1 LS2.ProgramStamp_LocalTime
    from table5 AS LS2 
    Where LS2.[Order] = OWS.Q2CNum
    AND LS2.LineItem= OWS.LineItem
    AND LS2.Identifier = OWS.Identifier
    Order by LS2.ProgramStamp_LocalTime Desc) 
AND LS.[Order] = @testVar
AND LS.LineItem = COALESCE('001',OWS.LineItem)
AND LS.Identifier like '%'
---Group by Q2CNum
ORDER BY Q2CNum, LineItem, Identifier DESC
FOR JSON Auto

最终更新

Mike Petri的方案可以实现需求,我调整后最终采用先将查询结果存入临时表,再通过嵌套子查询生成层级JSON的方案,受资源限制我没有使用视图,临时表方案更适合当前场景,最终代码如下:

IF OBJECT_ID('tempdb..#Temp') IS NOT NULL
BEGIN
    DROP TABLE #Temp;
END;

SELECT  OWS.Q2CNum
        ,OWS.LineItem
        ,OWS.Identifier
        ,OWS.ProductType
        ,OWS.Workstation
        ,OWS.Calculation
        ,OWS.UnitOfMeasure
        ,OWS.CurrentStatus
        ,LS.Location
        ,LS.ProgramStamp_LocalTime
INTO    #Temp
FROM    table1 AS OWS
        INNER JOIN table2 AS LS ON OWS.Q2CNum = LS.[Order]
                                   AND OWS.LineItem = LS.LineItem
                                   AND OWS.Identifier = LS.Identifier
WHERE   LS.ProgramStamp_LocalTime = (
                                        SELECT  TOP 1
                                                LS2.ProgramStamp_LocalTime
                                        FROM    talbe3 AS LS2
                                        WHERE   LS2.[Order] = OWS.Q2CNum
                                                AND LS2.LineItem = OWS.LineItem
                                                AND LS2.Identifier = OWS.Identifier
                                        ORDER BY
                                                LS2.ProgramStamp_LocalTime DESC
                                    )
        AND LS.[Order] = @testVar
        AND LS.LineItem = COALESCE('001', OWS.LineItem)
        AND LS.Identifier LIKE '%';

----REAL MAGIC HAPPENS HERE

SELECT t.Q2CNum
        ,(
             SELECT DISTINCT(t2.LineItem)
                    ,(
                         SELECT  DISTINCT(t3.Identifier)
                                ,t3.Location
                                ,t3.ProgramStamp_LocalTime
                                ,(
                                    SELECT   t4.Workstation
                                            ,t4.ProductType
                                            ,t4.Calculation
                                            ,t4.UnitOfMeasure
                                            ,t4.CurrentStatus
                                    FROM #Temp AS t4
                                    WHERE t3.Q2CNum = t4.Q2CNum and t3.LineItem = t4.LineItem and  t3.Identifier = t4.Identifier
                                    FOR JSON PATH 
                                ) AS Workstations
                        FROM #Temp AS t3
                        WHERE t3.Q2CNum = t2.Q2CNum and t2.LineItem = t3.LineItem
                        FOR JSON PATH
                     ) AS Identifiers
             FROM   #Temp AS t2
             WHERE  t.Q2CNum = t2.Q2CNum
             FOR JSON PATH
         ) AS LineItems
FROM    (
            SELECT  DISTINCT
                    Q2CNum
            FROM    #Temp
        ) AS t
FOR JSON AUTO;
DROP TABLE #Temp;

欢迎大家提出优化建议,我还有一个疑问:嵌套查询的WHERE条件应该仅关联直接父层级表即可,还是需要额外关联更上层的父表?


内容的提问来源于stack exchange,提问作者breeduss

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 22:06:03