• 牛客的课程订单分析[分组统计时如何取指定行字段?]


    前言

    对于group by时,select只能出现分组字段和聚集函数的结果,如何拿到其中任意一条记录的字段呐?可以配合SQL的语法,在外层套一个聚集函数在内if限定记录即可。

    一、牛客的课程订单分析

    在这里插入图片描述
    在这里插入图片描述

    二、窗口函数 & 聚集函数配if

    1、窗口min() & lead()

    with view4base as(
        select
            user_id,`date`,
            min(`date`) over(partition by user_id) first_buy_date,
            lead(`date`,1) over(partition by user_id order by `date`)  second_buy_date,
            count(1) over(partition by user_id) cnt
        from order_info
        where `date` > '2025-10-15'
            and product_name in('C++','Java','Python')
            and `status` = 'completed'
    )
    select user_id,first_buy_date,second_buy_date,cnt
    from view4base
    where cnt > 1 and `date` = first_buy_date
    order by user_id
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2、窗口min()+max(if())

    /*
    view中如果只拿第一次的日期该如何解决?
    如何拿第2日期呐?
    max() 配if + null,配合SQL语法,用max()也能拿到第二日期放在同一行。
    */
    with view4base as(
        select
            user_id,`date`,
            min(`date`) over(partition by user_id) first_buy_date
        from order_info
        where `date` > '2025-10-15'
            and product_name in('C++','Java','Python')
            and `status` = 'completed'
    )
    select 
        user_id,first_buy_date,
        min(if(`date` = first_buy_date,null,`date`)) second_buy_date,
        count(1) cnt
    from view4base
    group by user_id,first_buy_date
    having count(1) > 1
    order by user_id
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    3、窗口rank()+max(if())

    # 如果要第三第四等等,可以这种if比较繁琐,可max() + if + rank()让max只从一条记录中筛选。
    with view4base as(
        select
            user_id,`date`,
            rank() over(partition by user_id order by `date`) rk
        from order_info
        where `date` > '2025-10-15'
            and product_name in('C++','Java','Python')
            and `status` = 'completed'
    )
    select 
        user_id,min(`date`) first_buy_date,
        min(if(rk = 2,`date`,null)) second_buy_date,
        count(1) cnt
    from view4base
    group by user_id
    having count(1) > 1
    order by user_id
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    总结

    1)想把SQL玩的6,就必须有抽象的能力,我重来没想过在聚集函数里加if,甚至对字段做运算,甚至多字段,其实这都是可以的,把聚集函数内层当一个集合,而给什么集合自己可以随意。
    2)举一反三,那么窗口函数得到的排名值等各种值,其实也可以拿来当成运算,而不需要等到外层view。

    参考文献

    [1] 牛客SQL篇

  • 相关阅读:
    程序员5分钟,带你看完24岁60W年薪架构师的简历,上面竟然写着精通JVM
    DNS、ICMP和NAT
    ZCC5429 异步升压芯片
    MATLAB矩阵的行列式、MATLAB逆矩阵
    【Android】Android 项目里面为啥有两个地方设置Gradle
    SpringBoot集成Mybatis-Plus
    Operator3-设计一个operator
    32 | 未来之路:HTTP/3展望
    视频与png图片批量分类技巧:轻松管理文件
    Dubbo——通信框架与通信协议(dubbo协议)原理
  • 原文地址:https://blog.csdn.net/qq_43164662/article/details/126122832