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

s5a0g9ez  于 2023-01-16  发布在  Mysql
关注(0)|答案(3)|浏览(528)

我有这样一个查询,它以JSON字符串的形式返回产品名称和图像数组,但是,当产品没有附加图像时,我希望这个查询为images属性返回一个空数组。
目前,当找不到产品图像时,它返回以下内容:

{ "name": "Product Name", "images": [{"id": null, "slug": null}]}

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

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;

谢谢大家!

i1icjdpr

i1icjdpr1#

正如其他人所提到的,i.id = NULL的计算结果总是NULL,但是您的方法过于复杂,并且在严格配置的服务器上会引发错误。
组功能和字段的ER混合:在不带GROUP BY的聚集查询中,SELECT列表的表达式#2包含非聚集列'test.i.id';这与sql_mode=only_full_group_by不兼容
demo
因此,需要在GROUP_CONCAT()函数中执行检查i.id IS NULL

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

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

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;

demo

ryhaxcpt

ryhaxcpt2#

您应该使用IS NULL来检查NULL值:

SELECT
    p.name,
    CONCAT('[',
      GROUP_CONCAT(
        IF(id IS NULL,
           '',
           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
GROUP BY p.name;

顺便说一句,DISTINCT不是函数,您不应该这样使用它,所以我删除了您使用的函数括号。

**编辑:**已更新SQL以满足组限制。用于检查i.idGROUP_CONCAT之外的www.example.com的IF语句将失败,因为每行有多个图像项。

lhcgjxsq

lhcgjxsq3#

IF(i.id = NULL, ...)返回NULL,对于包含www.example.com的任何值(甚至NULL),这是一个伪值。i.id (even NULL ), which is a falsy value.
您希望使用IF (i.id IS NULL, ...)
documentation开始:
不能使用算术比较运算符(如=、〈或〈〉)来测试NULL。若要亲自演示这一点,请尝试以下查询:

mysql> SELECT 1 = NULL, 1 <> NULL, 1 < NULL, 1 > NULL;  
+----------+-----------+----------+----------+  
| 1 = NULL | 1 <> NULL | 1 < NULL | 1 > NULL |  
+----------+-----------+----------+----------+  
|     NULL |      NULL |     NULL |     NULL |  
+----------+-----------+----------+----------+

相关问题