mysql - GROUP_CONCAT 以多对多关系返回一个对象数组

标签 mysql sql json many-to-many aggregate-functions

我正在为个人项目处理 mySQL 查询。现在的最终目标是让查询为每个项目返回以下 json:

{
    "id": 1,
    "designName": "Slender Man",
    "designNotes": "Rewrite the lapel component",
    "quantity": 3,
    "colors": [
        {
        "id": 4,
        "colorName": "black",
        "colorSwatch": "rgb (0,0,0)",
        "brandName": "caron simply soft",
        "yarnWeightId": {
              "weightNumber": 4,
              "weightName": "medium/worst weight"
          }
        },{
        "id": 5,
        "colorName": "Off White",
        "colorSwatch": "rgb (255,255,255)",
        "brandName": "caron simply soft",
        "yarnWeightId": {
              "weightNumber": 4,
              "weightName": "medium/worst weight"
          }
        }
    ]
}

我最近的尝试是:

SELECT 
    d.id,
    d.designName,
    d.designNotes,
    d.quantity,
    d.isDeleted,
    GROUP_CONCAT(
        JSON_OBJECT(
            c.colorName,
            c.colorSwatch,
            c.brandName,
            yw.weightNumber,
            yw.weightName
        )
    ) AS colorsUsed
FROM designs AS d
    INNER JOIN design_colors AS dc 
        ON dc.designId = d.id
    INNER JOIN colors AS c 
        ON dc.colorId = c.id
    INNER JOIN yarnweights AS yw 
        ON c.yarnWeightId = yw.id
GROUP BY d.id
;

这给我一个内部服务器错误。使用更简单的查询对其进行测试可以正常进行,因此我将其范围缩小到查询本身就是问题所在。

下面的查询让我很接近:

SELECT 
    d.id,
    d.designName,
    d.designNotes,
    d.quantity,
    d.isDeleted,
    GROUP_CONCAT(
        DISTINCT c.id
        GROUP BY c.id
    ) AS colorsUsed
FROM designs AS d
    INNER JOIN design_colors AS dc 
        ON dc.designId = d.id
    INNER JOIN colors AS c 
        ON dc.colorId = c.id
    INNER JOIN yarnweights AS yw 
        ON c.yarnWeightId = yw.id
GROUP BY
    d.id

它返回的对象是这样的:

{
    "id": 3,
    "designName": "Slenderman",
    "designNotes": null,
    "quantity": 0,
    "isDeleted": 0,
    "colorsUsed": "4,5"
}

但是当我获取所有 colorsUsed 的 ID 时,我并没有将它们放入一个数组中,更不用说我需要的对象数组了。我觉得 GROUP_CONCAT 不是解决这个问题的正确方法,或者至少我没有正确使用它,但这是我一直试图找到解决方法时出现的问题。只是朝着正确的方向继续寻找也会有所帮助。


我的数据库结构如下: [数据库图][ /image/lxsvv.png]

最佳答案

您可以使用 MySQL JSON 函数生成有效的 JSON 对象,而不是使用 GROUP_CONCAT() 等字符串连接函数。 JSON_OBJECT() 可用于创建对象,JSON_ARRAYAGG() 是生成 JSON 数组的聚合函数。

首先,让我们从返回所有需要的列的查询开始:

SELECT 
    d.id,
    d.designName,
    d.designNotes,
    d.quantity,
    c.id,
    c.colorName,
    c.colorSwatch,
    c.brandName
    y.weightNumber,
    y.weightName
FROM 
    designs AS d
    INNER JOIN design_colors AS dc ON dc.designId = d.id
    INNER JOIN colors AS c ON dc.colorId = c.id
    INNER JOIN yarnweights AS y ON c.yarnWeightId = y.id

现在我们可以打开聚合并使用 JSON 函数生成预期的结果集:

SELECT JSON_OBJECT(
    'id', d.id,
    'designName', d.designName,
    'designNotes', d.designNotes,
    'quantity', d.quantity,
    'colors', JSON_ARRAYAGG(
        JSON_OBJECT(
            'id', c.id,
            'colorName', c.colorName,
            'colorSwatch', c.colorSwatch,
            'brandName', c.brandName
            'yarnWeightId', JSON_OBJECT(
                'weightNumber', y.weightNumber,
                'weightName', y.weightName
            )
        )
    ) AS myjson
FROM 
    designs AS d
    INNER JOIN design_colors AS dc ON dc.designId = d.id
    INNER JOIN colors AS c ON dc.colorId = c.id
    INNER JOIN yarnweights AS y ON c.yarnWeightId = y.id
GROUP BY
    d.id,
    d.designName,
    d.designNotes,
    d.quantity

这将返回一个具有唯一列的结果集,其中每条记录都包含预期的 JSON 对象。

关于mysql - GROUP_CONCAT 以多对多关系返回一个对象数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58245839/

相关文章:

mysql - 使用 MySQL 替换内容

php - 按 30 天内销量排序产品,然后是没有销量的产品

mysql - 用R还是mysql计算时间段 yield ?

SQL Server 不存在或 Access 被拒绝(间歇性)

mysql - 获取 MySQL 表中每小时的整数总和

javascript - ASP.NET MVC 重命名 JSON 对象包装器

java - jar执行期间资源路径改变

javascript - ionic 框架的动态数据

php - GCM 返回错误 : field data must be a json array

php - 从 url 中删除根路径