计算一列中某个值的个数

忆之独秀    https://blog.csdn.net/lavorange/article/details/25004181
这两天在参加阿里大数据竞赛,进入第二赛季要用到不少的SQL语句,现在才发现当时的数据库是白学了,今天就根据具体的需求来整理一下。可以把需求整理成为一道简单的题目,题目如下:

给定一个表t_alibaba_data:


user_id    brand_id    type    visit_datetime
10944750    13451    0    0604
10944750    13451    2    0604
10944750    13451    2    0723
10944750    13451    0    0801
10944750    13451    0    0515
10944750    13451    0    0703
10944750    13451    0    0629
10944750    13451    0    0814
10944750    21110    0    0422
10944750    1131    0    0713
…    …    …    …
其中:user_id代表用户,brand_id代表品牌,type代表操作的类型(0-点击,1-购买,2-收藏,3-购物车),visit_datetime即用户对品牌行为的时间(0415-0515,0516-0615,0616-0715,0716-0815四个月)。假设一共有10000条交易记录。
现在有这样的需求即:我现在需要对用户user_id对某一个品牌brand_id进行评分grade(可以理解为用户对品牌的喜爱程度),评分grade规则为用户对品牌不同类型type=0,1,2,3的操作总数,然后给这些总数乘以相应的权值grade = w0*count(type=0) + w1*count(type=1) + w2*count(type=2)+w3*count(type=3)。当然考虑到时间的因素,可以对靠后时间的点击操作提高权重,相对距离较远的点击操作降低权重,那么w0*count(type=0)可以改写成

w0*( 1*count(type=0 and 0716<=visit_datatime<=0815) + 0.8*count(type=0 and 0616<=visit_datatime<=0715) + 

0.6*count(type=0 and 0516<=visit_datetime<=0615)  + 0.4*count(type=0 and 0415<=visit_datetime<=0515)).现在就是要创建一个表user_brand_grade<user_id,brand_id,grade>,按照grade降序排列以便找到前1000个<user_id,brand_id>对。

Step1:首先不考虑时间的因素,首先要找到用户user_id对于某个品牌brand_id某种操作type=0/1/2/3的总次数。


SELECT user_id , brand_id , count(type=0) as type0 ,count(type=1) as type1 , count(type=2) as type2 ,count(type=3) as type3 FROM t_alibaba_data t
where visit_datetime >= 415 && visit_datetime <= 715
group by user_id,brand_id;
结果:

当我这么写完之后我发现type0,type1,type2,type3的值都是一样的。这非常不合理,才知道这么写是有问题的。
SQL语句count()的用法:http://www.w3school.com.cn/sql/sql_func_count.asp

可见count只能计算某一列的总数目,或者某一列符合一个条件的总数目,但不能计算某列符合多个条件的相应数目。

Step2:那么修改count成为sum加上type的条件可以做出相应的选择。


SELECT user_id , brand_id ,
sum(type=0) as type0,
sum(type=1) as type1,
sum(type=2) as type2,
sum(type=3) as type3
FROM t_alibaba_data t
where visit_datetime >=515 && visit_datetime <=815
group by user_id ,brand_id;
结果:

SQL语句sum()的用法:http://www.w3school.com.cn/sql/sql_func_sum.asp

sum中是可以加表达式的,因此可以加上type的相应值。

Step3:此时不禁要想,如果当type=0的时候,要根据visit_datetime选择不同的值怎么办?在此要用到case进行条件的选择。那么就可以重写Step2的SQL语句。


SELECT user_id , brand_id ,
sum(case when type=0 then 1 else 0 end) as type0,
sum(case when type=1 then 1 else 0 end) as type1,
sum(case when type=2 then 1 else 0 end) as type2,
sum(case when type=3 then 1 else 0 end) as type3
FROM t_alibaba_data t
group by user_id , brand_id ;
结果(应该和上图相同):


Step4:用case增加时间上的判断:


select * ,(type0+type1+type2+type3) as grade from (
SELECT user_id , brand_id ,
sum(case
        when type=0 && visit_datetime >= 801 && visit_datetime<=815 then 10
        when type=0 && visit_datetime >= 716 && visit_datetime<=731 then 8
        when type=0 && visit_datetime >= 701 && visit_datetime<=715 then 6
        when type=0 && visit_datetime >= 616 && visit_datetime<=630 then 4
        when type=0 && visit_datetime >= 601 && visit_datetime<=615 then 2
        when type=0 && visit_datetime >= 516 && visit_datetime<=531 then 1
    else 0
    end) as type0,
sum(case when type=1 then 1 else 0 end) as type1,
sum(case when type=2 then 2 else 0 end) as type2,
sum(case when type=3 then 3 else 0 end) as type3
FROM t_alibaba_data t
group by user_id , brand_id
order by type0 desc
)a
order by grade desc limit 1000;
然后得到结果:


那么就可以找到符合要求的<user_id,brand_id>对了,即最活跃的用户品牌对。

猜你喜欢

转载自blog.csdn.net/ywl470812087/article/details/89322318