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

如何基于两表的令牌列表字段关联查询用户允许访问的产品?

高效查询用户可访问产品的SQL方案

根据你的场景(1万产品、200用户,Web UI性能要求不极致),提供三种实用方案,从简单到高效按需选择:

方案一:直接字符串匹配(无需额外表)

不用改动现有表结构,通过字符串函数处理边界匹配,避免出现CZ和CZE这类部分匹配的问题。以MySQL为例:

SELECT DISTINCT p.*
FROM products p
JOIN users u ON u.user_id = ? -- 替换为当前用户ID
WHERE CONCAT(';', p.sales_country, ';') LIKE CONCAT('%;', REPLACE(u.sales_country, ';', ';%;'), ';')

原理:给产品和用户的国家字符串前后添加;,再把用户的国家列表转成%;XX;%的格式,用LIKE匹配任意重叠的国家码。这种方式虽然无法利用索引,但当前数据量完全够用,实现成本最低。

如果使用PostgreSQL,还可以用数组转换简化写法:

SELECT DISTINCT p.*
FROM products p
JOIN users u ON u.user_id = ?
WHERE string_to_array(p.sales_country, ';') && string_to_array(u.sales_country, ';')

方案二:优化映射表方案(兼顾性能与可维护性)

你提到的映射表思路可行,还能进一步简化实现逻辑:

  1. 产品映射表:每次products表刷新时,用数据库的字符串拆分工具(比如MySQL的REGEXP_SUBSTR、PostgreSQL的STRING_TO_TABLE),把sales_country拆入product_country表(字段:product_code、country_code),给这两个字段加联合主键(自动生成索引)。
  2. 用户映射表:用户更新账户设置时,同样拆分sales_country到user_country表(字段:user_id、country_code),加联合主键。

查询SQL简洁且能利用索引快速匹配:

SELECT DISTINCT p.*
FROM products p
JOIN product_country pc ON p.product_code = pc.product_code
JOIN user_country uc ON pc.country_code = uc.country_code
WHERE uc.user_id = ?

这种方式适合未来数据量增长的场景,性能比方案一更优,维护成本也不高——产品映射表跟着刷新任务自动重建,用户映射表在账户更新时触发即可。

方案三:改用数据库数组类型(最优简洁方案)

如果你的数据库支持数组类型(比如PostgreSQL、SQL Server),直接把sales_country字段改成数组类型:

  • 将products.sales_country改为text[](PostgreSQL)或nvarchar(max)数组(SQL Server),存储格式从CZ;SK变为['CZ','SK']
  • users.sales_country同理

查询时用数组交集运算符,代码最简洁,还能添加GIN索引提升性能:

-- PostgreSQL示例
SELECT DISTINCT p.*
FROM products p
JOIN users u ON u.user_id = ?
WHERE p.sales_country && u.sales_country -- && 表示两个数组存在交集

这种方式不需要维护额外表,代码可读性最高,是长期最优解,前提是数据库支持数组类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 18:55:56