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

MySQL中如何从JSON列指定层级查询含特定值的行?

问题描述

我有一个JSON列users.roles,结构如下:

{
    "tenant-foo":
    [
        "role-aaa",
        "role-bbb"
    ],
    "tenant-bar":
    [
        "role-bbb",
        "role-ccc"
    ],
    "tenant-buz":
    [
        "role-aaa",
        "role-ccc"
    ],
    ...
    "tenant-...": [
        "role-...",
        ...
    ]
}

语义说明:多租户系统中的用户角色,一个用户可被分配至多个租户,且在每个租户下拥有不同角色。

需求:仅筛选出roles列中存在role-aaa的用户行,能否仅通过SELECT语句结合JSON系列函数实现?如果可以,具体如何操作?

实现方案

可以实现,以下是主流关系型数据库的具体实现方式:

MySQL 方案

方法1:精准匹配第二层数组

利用JSON_TABLE将JSON对象的键(租户名)展开为行,再通过JSON_CONTAINS检查对应租户下的角色数组是否包含目标值:

SELECT u.*
FROM users u
JOIN JSON_TABLE(
    JSON_KEYS(u.roles),
    '$[*]' COLUMNS(tenant VARCHAR(255) PATH '$')
) AS tenant_rows
WHERE JSON_CONTAINS(u.roles->>CONCAT('$.', tenant_rows.tenant), '"role-aaa"');

方法2:快速全局查找

如果无需严格限制仅在第二层数组(比如确认JSON结构不会在其他层级出现role-aaa),可以直接用JSON_SEARCH判断是否存在目标值:

SELECT *
FROM users
WHERE JSON_SEARCH(roles, 'all', 'role-aaa') IS NOT NULL;

注:JSON_SEARCH会遍历整个JSON结构查找匹配值,若JSON存在其他层级可能出现该值的情况,优先用方法1。

PostgreSQL 方案

方法1:展开JSON对象筛选

通过jsonb_each将JSON对象拆分为租户名和对应角色数组的行,再用@>操作符检查数组是否包含目标角色:

SELECT DISTINCT u.*
FROM users u
JOIN jsonb_each(u.roles::jsonb) AS tenant_roles(tenant, role_list)
WHERE role_list @> '["role-aaa"]'::jsonb;

方法2:JSON路径查询

使用jsonb_path_exists通过JSON路径表达式直接匹配第二层数组包含目标值的情况:

SELECT *
FROM users
WHERE jsonb_path_exists(u.roles::jsonb, '$.values() ? (@ contains "role-aaa")');

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 23:21:10