mysql下做不匹配数据的统计sql写法
mysql

在mysql数据库中,我们习惯的使用left join 去查询两个表的数据。比如说,有这么一个表,我要去查询所有有java这个标签的文章。
1.png

当然,这个是 一个很简单表结构,我们要查出有java标签的,这个sql很简单。

select * from tags where tag='java'

结果很明显,也很简单
2.png



这是一个简单的需求,我们很容易就得到了结果,但是,我们如果需要统计标签里没有java的文章呢?首先,我们大概会想到用!去处理。

select * from tags where tag!='java'



3.png

通过结果,我们可以发现 ,并不如预期,因为ariticle_id 为5的文章是有java这个标签的。当然不会这么简单了,要不然,这篇文章的意义何在呢?经过思考,很多人会想到创造一个只有标签的关联表去查询,例如这样:

select t.article_id,any_value(case when t.tag=targetTags.tagName then tag end ) as matchTag,any_value(t.tag),targetTags.tagName from tags t
    left join (select 'java' as tagName from dual   ) targetTags on t.tag=targetTags.tagName
group by t.article_id,targetTags.tagName

运行看结果
4.png



结果不满足预期,期望结果是 不管能否匹配到,tageName这一列,应该是永远有值的。但是由于我们在关联条件用的是=,那么就肯定会有不满足的情况,怎么办呢,我们要想一个办法让on 右边的条件恒等于。

select t.article_id,any_value(case when t.tag=targetTags.tagName then tag end ) as matchTag,targetTags.tagName from tags t
    left join (select 'java' as tagName from dual   ) targetTags on 1
group by t.article_id,targetTags.tagName

这样就到位了,运行看结果:
5.png

妥了,满足预期,那么这个最终的sql如下:

select * from (
select t.article_id,any_value(case when t.tag=targetTags.tagName then tag end ) as matchTag,targetTags.tagName from tags t
left join (select 'java' as tagName from dual ) targetTags on 1
group by t.article_id,targetTags.tagName
) tags_result
where tags_result.matchTag is null

结果如下:
6.png



下面再深入点,我们进行多个标签的不匹配查询,要统计出,没有java,和没有php的文章。sql如下

select * from (
              select t.article_id,max(case when t.tag=targetTags.tagName then tag end ) as matchTag,targetTags.tagName from tags t
    left join (select 'java' as tagName from dual union all select 'php' as tagName  from dual  ) targetTags on 1
group by t.article_id,targetTags.tagName                  ) tags_result
where tags_result.matchTag is null
group by tags_result.article_id,tags_result.tagName



注意,由于排序的问题,这么的matchTag我们要用max函数包下,运行结果:
7.png



OK,基本可以满足做不匹配统计的需求了。当然,关系型数据库做统计还是差点意思,有条件的还是搞数仓吧。

暂无评论