SQL小挑战——第5期

查询所用的表:UserTag
表中有两列数据,一列是user_id ,一列是用户标签tag,每个用户可以拥有不同的标签,不同标签之间用英文逗号间隔。
SQL小挑战——第5期_第1张图片
UserTag表数据如下:

user_id tag
1045 css,go
56789 python,c,sql
7689 html,php,java
7543 spring,php,mysql,hive,css

1、输出每个标签的用户数?

2、谁拥有的标签最多?

3、哪个标签拥有用户最多?

首先,mysql需要将逗号隔开的字符串通过行列转换成如下

期望的表:

user_id tag
1045 css
1045 go
56789 python
56789 c
56789 sql
7689 html
7689 php
7689 java
7543 spring
7543 php
7543 mysql
7543 hive
7543 css

要完成上述行列转换,有以下几个步骤。
第一步:构建从0~5的一个自增表incre_table
SQL小挑战——第5期_第2张图片

create table incre_table (AutoIncreID int);
insert into incre_table values (0);
insert into incre_table values (1);
insert into incre_table values (2);
insert into incre_table values (3);
insert into incre_table values (4);
insert into incre_table values (5);

SQL小挑战——第5期_第3张图片
第二步:构造MySQL查询语句


select a.user_id,substring_index(substring_index(a.tag,',',b.AutoIncreID+1),',',-1) 
from 
UserTag a
join
incre_table b
on b.AutoIncreID < (length(a.tag) - length(replace(a.tag,',',''))+1)
order by a.user_id

SQL小挑战——第5期_第4张图片

其次,我们来解释一下实现该过程的原理

1、length(a.tag) - length(replace(a.tag,’,’,’’))+1计算的就是下面的元素个数
SQL小挑战——第5期_第5张图片
2、如果觉得整个查询语句比较难理解的话,可以先看看UserTag表join incre_table表的的笛卡尔积

select *,
length(ut.tag) - length(replace(ut.tag,',',''))+1 tag_length 
from 
UserTag ut 
join 
incre_table it
order by ut.user_id

得到如下结果:
SQL小挑战——第5期_第6张图片

以上join后得到的笛卡尔积结果,加上条件b.AutoIncreID < (length(a.tag) - length(replace(a.tag,’,’,’’))+1)后

select *,
length(ut.tag) - length(replace(ut.tag,',',''))+1 tag_length 
from 
UserTag ut 
join 
incre_table it
on it.AutoIncreID < (length(ut.tag) - length(replace(ut.tag,',',''))+1)
order by ut.user_id

得到结果为:
SQL小挑战——第5期_第7张图片
3、substring_index函数的用法

  1. substring_index(str,delim,count)

    str:要处理的字符串

    delim:分隔符

    count:计数
    例子1:substring_index(‘spring,php,mysql,hive,css’,’,’,1),是指字符串spring,php,mysql,hive,css以逗号分割,第三个参数1为正数,则说明是从左往右数,第一个分隔符左边的全部内容,为spring。
    例子2:substring_index(‘spring,php,mysql,hive,css’,’,’,-2),第三个参数-2为负数,则说明是从右往左数,第二个分隔符右边的全部内容,为hive,css。

最后,来做一下最开始的习题

CREATE temporary table tag_count --创建临时表,并将其命名为tag_count
select a.user_id,
substring_index(substring_index(a.tag,',',b.AutoIncreID+1),',',-1) tag
from 
UserTag a
join
incre_table b
on b.AutoIncreID < (length(a.tag) - length(replace(a.tag,',',''))+1)

--1、输出每个标签的用户数?
select tag,count(distinct user_id)
from tag_count
group by tag

--2、谁拥有的标签最多?
select user_id
from tag_count
group by user_id
order by count(distinct tag) desc
limit 1

--3、哪个标签拥有用户最多?
select tag
from tag_count
group by tag
order by count(distinct user_id) desc
limit 1

另外,group_contact()函数能将多条记录转换成单条记录

select user_id,GROUP_CONCAT(tag SEPARATOR ',') from tag_count group by user_id

结果为:
SQL小挑战——第5期_第8张图片

你可能感兴趣的:(SQL)