如何从 MySQL CONCAT 和 GROUP_CONCAT 中跳过 NULL 值

Csa*_*aba 3 mysql

我有一个查询,它返回产品名称和图像数组作为 JSON 字符串。但是,当产品没有附加图像时,我希望此查询返回该images属性的空数组。

目前,当未找到产品图片时,它会返回此信息:

{ "name": "Product Name", "images": [{"id": null, "slug": null}]}
Run Code Online (Sandbox Code Playgroud)

我尝试将 IF 条件添加到 CONCAT 方法中,但它返回相同的响应。

SELECT p.name,
CONCAT('[',
          IF(i.id = NULL,
            '',
            GROUP_CONCAT(DISTINCT (
              JSON_OBJECT(
                'id', i.id, 
                'slug', i.slug
              )
            ))
          ),
       ']') AS images
FROM products AS p
        LEFT JOIN _product_images AS pi ON pi.pId = p.id
        LEFT JOIN images AS i ON i.id = pi.iId
WHERE p.id = 4;
Run Code Online (Sandbox Code Playgroud)

谢谢你!

Pau*_*gel 5

正如其他人提到的,i.id = NULL将始终评估为NULL。但是您的方法不必要地复杂,并且会在严格配置的服务器上引发错误。在 db-fiddle 上我收到以下错误:

ER_MIX_OF_GROUP_FUNC_AND_FIELDS:在没有 GROUP BY 的聚合查询中,SELECT 列表的表达式#2 包含非聚合列“test.i.id”;这与 sql_mode=only_full_group_by 不兼容

演示

所以检查i.id IS NULL需要在函数内完成GROUP_CONCAT():

SELECT p.name,
CONCAT('[',
  GROUP_CONCAT(DISTINCT (
    IF (i.id IS NULL, '',
      JSON_OBJECT(
        'id', i.id, 
        'slug', i.slug
       )
    )
   )),
']') AS images
FROM products AS p
        LEFT JOIN _product_images AS pi ON pi.pId = p.id
        LEFT JOIN images AS i ON i.id = pi.iId
WHERE p.id = 4
Run Code Online (Sandbox Code Playgroud)

但是 - 当您使用 INNER JOIN 时,您可以避免检查。但 INNER JOIN 也会忽略表中的数据products- 所以我会在相关子查询中执行该 JOIN。最后,您可以使用它JSON_ARRAYAGG()来生成 JSON 数组。

演示

SELECT p.name, COALESCE((
  SELECT JSON_ARRAYAGG(JSON_OBJECT(
    'id', i.id, 
    'slug', i.slug
  ))
  FROM _product_images AS pi 
  JOIN images AS i ON i.id = pi.iId
  WHERE pi.pId = p.id
), JSON_ARRAY()) AS images
FROM products AS p
#WHERE p.id = 4;
Run Code Online (Sandbox Code Playgroud)

演示