使用数据库mysql

设置表用户表(test)、关系表(test2),筛选项直接传入label_id,所以这两张表应该够用了

实现思路:标签筛选项作为入参,如果筛选标签是用户已绑定标签的子集,则匹配数据

最先想到的是mysql函数 find_in_set

尝试后find_in_set只能单条数据匹配,无法子集匹配

启动搜索(公司无法访问g)参考文章

MySQL中利用help_topic实现行转列_Lens5935的博客-CSDN博客_mysql.help_topic

在这个sql的基础上做改造

select a.id,substring_index(substring_index(a.value,',',b.help_topic_id+1),',',-1)  as value
source_table a
mysql.help_topic b
on b.help_topic_id < (length(a.value) - length(replace(a.value,',',''))+1)
order by a.id;
————————————————
版权声明:本文为CSDN博主「Lens5935」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_40983094/article/details/116204678

替换为自己的表

select substring_index(substring_index('a,b',',',help_topic_id+1),',',-1) filterIds,labelIds
    from (select group_concat(label_id) labelIds from query_test2 group by user_id) a
    inner join mysql.help_topic b on b.help_topic_id < (length('a,b') - length(replace('a,b',',',''))+1)

这样就获得了用户所有的标签id聚合和需要筛选id了

下一步只要找出筛选id是标签id的子集就可以了

这里想到了find_in_set

select substring_index(substring_index('a,b',',',help_topic_id+1),',',-1) filterIds,labelIds,find_in_set(substring_index(substring_index('a,b',',',help_topic_id+1),',',-1),labelIds) inSet
    from (select group_concat(label_id) labelIds from query_test2 group by user_id) a
    inner join mysql.help_topic b on b.help_topic_id < (length('a,b') - length(replace('a,b',',',''))+1)

可以看到筛选id再每一个标签id中的位置(inSet),这个时候就需要用user_id在做一次聚合了,聚合后取位置的SUM值或者count值,用来判断是否为子集。以SUM为例最终结果会是位置和,例如:1+2或1+3

select
    SUM(find_in_set(substring_index(substring_index('a,b',',',help_topic_id+1),',',-1),labelIds)) inSetSUM,user_id
from (select group_concat(label_id) labelIds,user_id from query_test2 group by user_id) a
         inner join mysql.help_topic b on b.help_topic_id < (length('a,b') - length(replace('a,b',',',''))+1)
group by user_id

接下来只需要判断数量是否匹配就可以了,从数据中可以看出,需要匹配的标签有两个,那么最小SUM值应该是1+2=3那么大于3的就是我们想要的结果,再加上主表去做过滤

select * from query_test u left join (select
    SUM(find_in_set(substring_index(substring_index('a,b',',',help_topic_id+1),',',-1),labelIds)) inSetSUM,user_id
from (select group_concat(label_id) labelIds,user_id from query_test2 group by user_id) a
         inner join mysql.help_topic b on b.help_topic_id < (length('a,b') - length(replace('a,b',',',''))+1)
group by user_id ) labelHit on u.id = labelHit.user_id
where labelHit.inSetSUM >= 3

那么大致实现已经完成了,效率先不考虑(技术债+1)

分割线分割线分割线分割线分割线分割线分割线分割线分割线分割线分割线分割线分割线分割线分

问题1:排序问题

我们可以从上面labelIds中看到,聚合后的顺序是与入参顺序一致的,那么当聚合后顺序改变了,就会对SUM值产生影响。例如实际在测试时labelIds出现了如下顺序

c,d,e,f,g,h,a

那么当我匹配a,b时,SUM值变成了7。明显7是大于3的,命中了错误的数据。

这里就需要对labelIds进行一个排序,顺序需要与过滤标签的顺序保持一致(如果有相同值的话)

所以对labelIds增加排序

select * from query_test u left join (select
    SUM(find_in_set(substring_index(substring_index('a,b',',',help_topic_id+1),',',-1),labelIds)) inSetSUM,user_id
from (select group_concat(label_id order by case label_id when 'a' then 1 when 'b' then 2 else 3 end) labelIds,user_id from query_test2 group by user_id) a
         inner join mysql.help_topic b on b.help_topic_id < (length('a,b') - length(replace('a,b',',',''))+1)
group by user_id ) labelHit on u.id = labelHit.user_id
where labelHit.inSetSUM >= 3

这样就解决了上面的问题

或者用count

select * from query_test u left join (select count(inSet) inSetC,user_id from(select
  find_in_set(substring_index(substring_index('a,b',',',help_topic_id+1),',',-1),labelIds) inSet,user_id
from (select group_concat(label_id) labelIds,user_id from query_test2 group by user_id) a
       inner join mysql.help_topic b on b.help_topic_id < (length('a,b') - length(replace('a,b',',',''))+1)
 ) t where t.inSet > 0 group by user_id) labelHit on u.id = labelHit.user_id
where labelHit.inSetC >= 2

因为我不会写,所以又加了一层select,凑合看吧

pg_attribute aa LEFT JOIN pg_class AS cc ON aa.attrelid = cc.oid LEFT JOIN pg_description AS dd ON dd.objoid = cc.oid WHERE dd.description IS NULL select * from all_tab_comments – 查询 所有用户的表,视图等  select * from user_tab_comments – 查询 本用户的表,视图等  select * from all_col_comments – 查询 所有用户的表的列名和注释.  select * from user_col_comments – 查
以下讲一些 SQL 中通过关键字 筛选 数据的用法: 以某学校数据库为例: 1.select distinct: 筛选 表中指定的属性,将不同的属性值进行分类返回(相同的值不会重复返回),NULL也作为一种属性值 (1) 查询 学生表中学生性别种类(NULL即表明学生表中有未编辑性别的学生): 语法:select distinct 属性 from 表名; 2.where:从表中获取满足 筛选 条件一行或多行数据 (1) 查询 性别为男的所有学生信息(单表条件 查询 ) 语法:select 字段1,字段2 from 表名 where
我现在要批量往数据库中插入数据(xxx证件),这个证件根据证件代码和号码确定唯一,待插入的批量数据里面有些数据,在数据库里面有可能已经存在。 我现在的目的是:批量插入,如果该证件已经存在,就忽略。我想到的做法就是:遍历这个 待插入的批量数据,每一个按照代码和号码去数据库中 查询 ,查到了就跳过,没 查询 到就新增。但是这个 待插入的批量数据 可能很大,我要遍历他,然后循环的去数据库中按照代码、号码 查询 ,循环的去操作数据库,这样操作数据库压力很大。 所以我的想法是:想根据这个 待插入的批量数据去数据库中 查询
前面讲到的 SQL 查询 只包含从一个或多个表中返回数据的单条 SELECT 语句。 SQL 也允许执行多个 查询 (多条 SELECT 语句),并将结果作为一个 查询 结果集返回,这些组合 查询 通常称为复合 查询 。 主要有两种情况需要使用组合 查询 : 1.对一个表执行多个 查询 ,按一个 查询 返回数据。 2.从不同的表返回数据。 组合 查询 使用关键字 UNION,使用 UNION 很简单,所要做的只是给出每条 SELECT 语句,在各条 SELECT 语句之间放上关键字 UNION。 举个例子,我们根据订单的日期将订单归到相应的月
您可以使用IN关键字来 实现 动态多个省份 查询 。例如,如果您的省份 择器返回一个包含所 省份ID的数组,您可以使用以下 SQL 查询 : SELECT * FROM 表名 WHERE 省份ID IN (1, 2, 3) 其中,1、2、3是所 省份的ID。您可以使用编程语言将所 省份ID转换为逗号分隔的字符串,然后将其插入到IN子句中。这样,您就可以动态地构建 SQL 查询 ,以支持多个省份的 择。