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

SQL多表关联后JSON_ARRAYAGG生成的参数数组出现重复项问题求助

Fixing Duplicate Entries in JSON Array When Joining Multiple Tables

Hey there! Let’s break down what’s going on with your query and fix that duplicate parameter issue you’re seeing.

Why the Duplicates Are Happening

You’re spot-on with your hunch—this is caused by a cartesian product from joining multiple unrelated tables. When you join rooms to both roomdevices (which links to devices) and roomdata in the same query, there’s no direct relationship between roomdevices and roomdata.

For example: If a room has 2 devices and 1 parameter, the join will create 2 separate rows (one for each device paired with the single parameter). When json_arrayagg runs, it picks up that parameter twice—once for each device row.

Solution 1: Pre-Aggregate Room Data (Most Reliable)

The cleanest fix is to aggregate your roomdata into the JSON array before joining it to the rest of the tables. This way, you avoid the cartesian product entirely.

Here’s the adjusted query:

SELECT 
    r.identifier, 
    r.room_name, 
    COALESCE(rdata.parameters, JSON_ARRAY()) AS parameters,
    COALESCE(json_arrayagg(JSON_OBJECT(
        "identifier", d.identifier, 
        "friendly_name", d.friendly_name, 
        "type", d.type, 
        "gateway", d.gateway
    )), JSON_ARRAY()) AS devices 
FROM rooms AS r 
LEFT JOIN roomdevices AS rd ON rd.room_identifier = r.identifier 
LEFT JOIN devices AS d ON d.identifier = rd.device_identifier 
LEFT JOIN (
    -- Subquery to pre-aggregate room parameters into a JSON array
    SELECT 
        room_identifier,
        json_arrayagg(JSON_OBJECT("key", parameter_key, "value", value)) AS parameters
    FROM roomdata
    GROUP BY room_identifier
) AS rdata ON rdata.room_identifier = r.identifier 
GROUP BY r.identifier, r.room_name, rdata.parameters

I added COALESCE here to return an empty JSON array (JSON_ARRAY()) for rooms with no parameters or devices, instead of NULL—this makes the output more consistent.

Solution 2: Use DISTINCT in json_arrayagg (Quick Fix, Caveats)

If you want a simpler tweak, you can add DISTINCT inside the json_arrayagg for parameters. This will deduplicate the JSON objects in the array.

Note: Only use this if you’re sure you’ll never have legitimate duplicate parameters (same key and value) for a single room—this method will remove those too.

Example:

SELECT DISTINCT 
    r.identifier, 
    r.room_name, 
    COALESCE(json_arrayagg(DISTINCT JSON_OBJECT("key", rdata.parameter_key, "value", rdata.value)), JSON_ARRAY()) AS parameters, 
    COALESCE(json_arrayagg(JSON_OBJECT(
        "identifier", d.identifier, 
        "friendly_name", d.friendly_name, 
        "type", d.type, 
        "gateway", d.gateway
    )), JSON_ARRAY()) AS devices 
FROM rooms AS r 
LEFT JOIN roomdevices AS rd ON rd.room_identifier = r.identifier 
LEFT JOIN devices AS d ON d.identifier = rd.device_identifier 
LEFT JOIN roomdata as rdata ON rdata.room_identifier = r.identifier 
GROUP BY r.identifier

Why Your First Query Worked

In your initial query, you only joined rooms → roomdevices → devices—this is a chain of one-to-many relationships, so no cartesian product was created. Each room’s devices are linked directly through roomdevices, so the aggregation worked as expected.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 15:52:28