您的位置:首页 > 数据库

简单的SQL语句:计算一列中某个值的个数

2014-05-05 22:39 190 查看
这两天在参加阿里大数据竞赛,进入第二赛季要用到不少的SQL语句,现在才发现当时的数据库是白学了,今天就根据具体的需求来整理一下。可以把需求整理成为一道简单的题目,题目如下:

给定一个表t_alibaba_data:

user_idbrand_idtypevisit_datetime
109447501345100604
109447501345120604
109447501345120723
109447501345100801
109447501345100515
109447501345100703
109447501345100629
109447501345100814
109447502111000422
10944750113100713
其中: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>对了,即最活跃的用户品牌对。

转载注明出处:http://blog.csdn.net/lavorange/article/details/25004181
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  sql 数据库 count sum