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

如何在MySQL中筛选JSON_ARRAYAGG生成的convenients数组元素?

MySQL实现JSON数组包含指定元素的筛选

问题背景

你现有如下SQL语句,通过子查询的JSON_ARRAYAGG生成了名为convenients的JSON数组列:

SELECT 
    h.id,
    h.name,
    h.address,
    JSON_OBJECT(
    "lat", h.latitude,
    "lng", h.longitude) coordinate,
    h.price,
    h.guest_max guestMax,
    h.bedrooms,
    h.beds,
    h.bathrooms,
    h.thumbnail_url thumbNailUrl,
    h.user_id,
    h.area_id,
    ha.name areaName,
    (SELECT JSON_ARRAYAGG(c.name) FROM hotel_convenient hc INNER JOIN convenients c ON c.id = hc.convenient_id WHERE hc.hotel_id = h.id) convenients
  FROM hotels h
  INNER JOIN hotel_areas ha ON h.area_id = ha.id 
  INNER JOIN hotel_convenient hc ON hc.hotel_id = h.id
  INNER JOIN convenients c ON hc.convenient_id = c.id
  GROUP BY h.id
  ORDER BY h.id ASC;

该语句生成的convenients列格式为:

["foo", "bar", "baz"]

需要实现类似JavaScript中Array.prototype.includes()的功能,筛选出convenients数组包含指定元素(比如'foo'、'bar')的记录。

解决方案

方法1:使用JSON_CONTAINS函数

MySQL内置的JSON_CONTAINS函数可直接判断JSON数组是否包含指定元素,语法为JSON_CONTAINS(target_json, search_value)。将其加入查询的WHERE子句即可:

SELECT 
    h.id,
    h.name,
    h.address,
    JSON_OBJECT(
    "lat", h.latitude,
    "lng", h.longitude) coordinate,
    h.price,
    h.guest_max guestMax,
    h.bedrooms,
    h.beds,
    h.bathrooms,
    h.thumbnail_url thumbNailUrl,
    h.user_id,
    h.area_id,
    ha.name areaName,
    (SELECT JSON_ARRAYAGG(c.name) FROM hotel_convenient hc INNER JOIN convenients c ON c.id = hc.convenient_id WHERE hc.hotel_id = h.id) convenients
  FROM hotels h
  INNER JOIN hotel_areas ha ON h.area_id = ha.id 
  INNER JOIN hotel_convenient hc ON hc.hotel_id = h.id
  INNER JOIN convenients c ON hc.convenient_id = c.id
  WHERE JSON_CONTAINS(
      (SELECT JSON_ARRAYAGG(c.name) FROM hotel_convenient hc INNER JOIN convenients c ON c.id = hc.convenient_id WHERE hc.hotel_id = h.id),
      '"foo"' -- JSON字符串需用双引号包裹
  )
  GROUP BY h.id
  ORDER BY h.id ASC;
  • 若需同时包含多个元素(逻辑与),叠加多个JSON_CONTAINS用AND连接
  • 若需包含任意一个元素(逻辑或),用OR连接多个JSON_CONTAINS

方法2:优化查询,避免重复子查询

原查询主语句中的INNER JOIN hotel_convenient和INNER JOIN convenients属于冗余关联,可通过EXISTS子句直接从关联表筛选,效率更高:

SELECT 
    h.id,
    h.name,
    h.address,
    JSON_OBJECT("lat", h.latitude, "lng", h.longitude) coordinate,
    h.price,
    h.guest_max guestMax,
    h.bedrooms,
    h.beds,
    h.bathrooms,
    h.thumbnail_url thumbNailUrl,
    h.user_id,
    h.area_id,
    ha.name areaName,
    (SELECT JSON_ARRAYAGG(c.name) 
     FROM hotel_convenient hc 
     INNER JOIN convenients c ON c.id = hc.convenient_id 
     WHERE hc.hotel_id = h.id) convenients
FROM hotels h
INNER JOIN hotel_areas ha ON h.area_id = ha.id 
WHERE EXISTS (
    SELECT 1 
    FROM hotel_convenient hc 
    INNER JOIN convenients c ON c.id = hc.convenient_id 
    WHERE hc.hotel_id = h.id 
    AND c.name IN ('foo', 'bar')
)
GROUP BY h.id
ORDER BY h.id ASC;

这种方式无需处理JSON格式字符串,直接通过关联表筛选,避免了JSON函数的额外开销。

方法3:使用JSON_SEARCH函数

JSON_SEARCH会返回指定元素在JSON数组中的路径,若返回非NULL则说明包含该元素:

WHERE JSON_SEARCH(
    (SELECT JSON_ARRAYAGG(c.name) FROM hotel_convenient hc INNER JOIN convenients c ON c.id = hc.convenient_id WHERE hc.hotel_id = h.id),
    'one', -- 'one'匹配第一个结果,'all'匹配所有结果
    'foo'
) IS NOT NULL

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 17:33:10