MySQL json_arrayagg与左连接没有结果

时间:2018-04-21 20:57:41

标签: mysql

在MySQL 8.0中引入了json_arrayagg,这使得聚合json结果成为可能。

现在我想用它来显示附加到邮件的标签。

目前有三个表(简单)

CREATE TABLE IF NOT EXISTS feed_message (
  id CHAR(36) PRIMARY KEY
);

CREATE TABLE IF NOT EXISTS feed_tag (
  id CHAR(36) PRIMARY KEY,
  name VARCHAR(30) NOT NULL
);

CREATE TABLE IF NOT EXISTS feed_message_tag (
  message CHAR(36) NOT NULL,
  tag CHAR(36) NOT NULL,

  PRIMARY KEY (message, tag)
);

因此,有一个表包含消息,一个包含所有标记,一个表包含标记和消息之间的连接(feed_message_tag)。

我正在寻找的响应是一个带有一列标签的消息列表,这些标签是一个带有id + name的对象数组。所以接下来的事情

[{"id": 1, "name": "Foo"}]

现在我发现的示例使用(内部)连接,这意味着消息必须具有标记,但并非总是如此,因此使用了左连接。这让我想到了以下使用的查询

SELECT
  json_arrayagg(
      json_object(
          'id',
          ft.id,
          'name',
          ft.name
      )
  ) as 'tags'
FROM feed_message fm
LEFT JOIN feed_message_tag fmt ON fmt.message = fm.id
LEFT JOIN feed_tag ft ON fmt.tag = ft.id
GROUP BY fm.id

现在的问题是,如果一条消息没有标签,我会得到以下输出tags

[{"id": null, "name": null}]

经过一些搜索和调整后,我对tags列进行了以下更改

IF(
    fmt.message IS NULL,
    json_array(),
    json_arrayagg(
      json_object(
        'id',
        ft.id,
        'name',
        ft.name
      )
    )
  ) as 'tags'

这是预期的行为还是我做错了什么?

1 个答案:

答案 0 :(得分:0)

似乎你的方法可能是唯一的方法。

原因是NULL是包含在JSON对象中的有效值。虽然大多数聚合函数都忽略空值,但它们正确地忽略来自LEFT JOIN的不匹配行,这对JSON_ARRAYAGG()来说是个问题。它会阻止您在其他情况下包含空值。没有办法将显式空值与LEFT JOIN空值区分开来。