美文网首页
小小SQL系列--前10%,后10%的使用

小小SQL系列--前10%,后10%的使用

作者: 统计小白er | 来源:发表于2022-01-27 11:18 被阅读0次

    今天看了道SQL题目,是《SQL数据分析》书中第15章 17个中等难度的SQL题目 的第二道题目。

    首先,介绍一下数据表:

    一张App累计下载情况表app_download,该表记录了应用商店中App累计下载次数的信息,包含如下3个字段。

    字段(字段含义)类型

    app_id(App ID)VARCHAR

    app_type(App类型)VARCHAR

    download(下载次数)INT

    app_download表的数据如下表所示:

    建表脚本如下:

    需求:查询不同类型App的平均下载次数,需要将平均下载次数排在前10%与后10%的App排除在外。

    解题:

    这里使用rank()函数根据下载数进行排序。

    SELECT a.app_type ,AVG(a.download) AS avg_download

    FROM

    (

        SELECT *

        ,RANK() OVER (ORDER BY download DESC) AS ranking

        FROM app_download

    ) a

    WHERE a.ranking>(

        SELECT COUNT(*)

        FROM app_download)*0.1

    AND a.ranking<(

        SELECT COUNT(*)

        FROM app_download)*0.9

    GROUP BY a.app_type;

    这里给的建表数据是10条,在上述脚本中,去掉的排名是1,9,10三条数据。

    当时的疑惑就是选取了5条,然后他们的排名依次是1,1,3,3,5.这个时候,5*0.1=0.5,5*0.9=4.5.选择两者之间的数据就是1,1,3,3.明显不是去掉了前10%和后10%。

    这里想到了10%和第10百分位数的联系:

    将一列数按大小排序,第XX位百分位数是指这列数中有XX%的数的值比这个数要小。即第10百分位数是指数列中有10%的数小于此数。

    正常的第10百分位数 怎么理解第10百分位数的概念.

    计算方式:

    https://zhidao.baidu.com/question/1641558612305725100.html

    因为细拆脚本,发现上述脚本有点问题,然后自己进行了新的脚本的编辑,对这部分内容,自己也是刚刚百度学习到的,可能会有错误,希望如果有错误,可以及时提醒我,谢谢~

    下面将两种脚本及其输出进行比对,发现其不同。

    (现在数据表是奇数条,如下所示)

    第一种,就是书中描写的:

    SELECT *

    FROM

    (

        SELECT *

        ,row_number() OVER (ORDER BY download DESC) AS ranking

        FROM app_download

    ) a

    WHERE a.ranking>((select count(*)

    from app_download ) * 0.1)

    AND a.ranking<((select count(*)

    from app_download ) * 0.9)

    ;

    结果:

    其结果仅仅删除了排名第9的数据。

    第二种,自己补充的,涉及到百分位数的概念:

    SELECT *

    FROM

    (

        SELECT *

        ,row_number() OVER (ORDER BY download DESC) AS ranking

        FROM app_download

    ) a

    WHERE a.ranking>(select

    if(mod(

    (select count(*)

    from app_download ) * 0.1

    ,1)=0,

    ((ceil((select count(*)

    from app_download ) * 0.1))+((ceil((select count(*)

    from app_download ) * 0.1))+1))/2,

    ceil((select count(*)

    from app_download ) * 0.1)

    ))

    AND a.ranking<(select

    if(mod(

    (select count(*)

    from app_download ) * 0.9

    ,1)=0,

    ((ceil((select count(*)

    from app_download ) * 0.9))+((ceil((select count(*)

    from app_download ) * 0.9))+1))/2,

    ceil((select count(*)

    from app_download ) * 0.9)

    ))

    ;

    结果:

    这里去掉了排名第1和第9的数据,比较符合预期。

    这里为了防止出现bug,再查看一下数据为偶数条的情况:

    数据如下:

    第一种结果:

    还是仅去掉了排名第8的数据。

    第二种结果:

    相关文章

      网友评论

          本文标题:小小SQL系列--前10%,后10%的使用

          本文链接:https://www.haomeiwen.com/subject/ipfahrtx.html