zoukankan      html  css  js  c++  java
  • 在拉链表中取用户每个月最后一天的状态

    with data as (
        select 
            t1.*
            ,row_number() over(partition by id order by end_date desc) as rn
        from (
            select 1 as id,20 as status,'2020-03-28' as start_date,'2020-04-05' as end_date union all
            select 1 as id,10 as status,'2020-04-05' as start_date,'2020-04-20' as end_date union all
            select 1 as id,30 as status,'2020-04-21' as start_date,'2020-05-02' as end_date union all
            select 2 as id,20 as status,'2020-01-28' as start_date,'2020-04-05' as end_date
        ) t1
    ) -- 1. 测试数据
    -- select * from data;
    ,cal as (
        select 
            month
            ,last_day(month) as month_last_day
            ,date_add(month, interval - day(month) + 1 day) as month_first_day
        from (
            select '2020-01-01' as month union all
            select '2020-02-01' as month union all
            select '2020-03-01' as month union all
            select '2020-04-01' as month union all
            select '2020-05-01' as month union all
            select '2020-06-01' as month union all
            select '2020-07-01' as month union all
            select '2020-08-01' as month union all
            select '2020-09-01' as month union all
            select '2020-10-01' as month union all
            select '2020-11-01' as month union all
            select '2020-12-01' as month
        ) t1
    ) -- 2. 日历
    -- select * from cal;
    ,id_max_day as (
        select 
             id
            ,min(start_date) as start_date
            ,max(end_date) as end_date
        from data
        group by 
            id
    ) -- 3. 取出id的最大值和最小值
    -- select * from id_max_day;
    ,id_month as (
        select
            t1.*,t2.month,t2.month_last_day,t2.month_first_day
        from id_max_day t1
        inner join cal t2
            on 1 = 1
        where t2.month >= DATE_ADD(t1.start_date,interval -day(t1.start_date)+1 day) -- 开始时间的当月第一天
            and t2.month <=  t1.end_date
    ) -- 4. 获取所有id的取数范围
    -- select * from id_month order by id,month;
    select
        -- t1.*,t2.*
         t1.id
        ,t1.status
        ,t2.month
    from data t1
    inner join id_month t2
        on t1.id = t2.id
    where t1.start_date <= t2.month_last_day
        and 
            case 
            when t1.rn = 1 then last_day(t1.end_date) >= t2.month_last_day
            else t1.end_date >= t2.month_last_day
            end
    order by t1.id,t2.month 
    ;
    
    +----+--------+------------+------------+----+------------+------------+------------+----------------+-----------------+
    | id | status | start_date | end_date   | id | start_date | end_date   | month      | month_last_day | month_first_day |
    +----+--------+------------+------------+----+------------+------------+------------+----------------+-----------------+
    |  1 |     20 | 2020-03-28 | 2020-04-05 |  1 | 2020-03-28 | 2020-05-02 | 2020-03-01 | 2020-03-31     | 2020-03-01      |
    |  1 |     30 | 2020-04-21 | 2020-05-02 |  1 | 2020-03-28 | 2020-05-02 | 2020-04-01 | 2020-04-30     | 2020-04-01      |
    |  2 |     20 | 2020-01-28 | 2020-04-05 |  2 | 2020-01-28 | 2020-04-05 | 2020-01-01 | 2020-01-31     | 2020-01-01      |
    |  2 |     20 | 2020-01-28 | 2020-04-05 |  2 | 2020-01-28 | 2020-04-05 | 2020-02-01 | 2020-02-29     | 2020-02-01      |
    |  2 |     20 | 2020-01-28 | 2020-04-05 |  2 | 2020-01-28 | 2020-04-05 | 2020-03-01 | 2020-03-31     | 2020-03-01      |
    +----+--------+------------+------------+----+------------+------------+------------+----------------+-----------------+
    
    -- 1. 测试数据
    +----+--------+------------+------------+
    | id | status | start_date | end_date   |
    +----+--------+------------+------------+
    |  1 |     20 | 2020-03-28 | 2020-04-05 | 2020-03-01
    |  1 |     10 | 2020-04-05 | 2020-04-20 |
    |  1 |     30 | 2020-04-21 | 2020-05-02 |
    |  2 |     20 | 2020-01-28 | 2020-04-05 |
    +----+--------+------------+------------+
    
    +----+--------+------------+
    | id | status | month      |
    +----+--------+------------+
    |  1 |     20 | 2020-03-01 |
    |  1 |     30 | 2020-04-01 |
    |  1 |     30 | 2020-05-01 |
    |  2 |     20 | 2020-01-01 |
    |  2 |     20 | 2020-02-01 |
    |  2 |     20 | 2020-03-01 |
    |  2 |     20 | 2020-04-01 |
    +----+--------+------------+
    
    
    
    -- 3. 取出id的最大值和最小值
    +----+------------+------------+
    | id | start_date | end_date   |
    +----+------------+------------+
    |  1 | 2020-03-28 | 2020-05-02 |
    |  2 | 2020-01-28 | 2020-04-05 |
    +----+------------+------------+
    
    -- 4. 获取所有id的取数范围
    +----+------------+------------+------------+
    | id | start_date | end_date   | month      |
    +----+------------+------------+------------+
    |  1 | 2020-03-28 | 2020-05-02 | 2020-03-01 |
    |  1 | 2020-03-28 | 2020-05-02 | 2020-04-01 |
    |  1 | 2020-03-28 | 2020-05-02 | 2020-05-01 |
    |  2 | 2020-01-28 | 2020-04-05 | 2020-01-01 |
    |  2 | 2020-01-28 | 2020-04-05 | 2020-02-01 |
    |  2 | 2020-01-28 | 2020-04-05 | 2020-03-01 |
    |  2 | 2020-01-28 | 2020-04-05 | 2020-04-01 |
    +----+------------+------------+------------+
    
    -- 最终结果
    +----+--------+------------+------------+----+------------+------------+------------+
    | id | status | start_date | end_date   | id | start_date | end_date   | month      |
    +----+--------+------------+------------+----+------------+------------+------------+
    |  1 |     20 | 2020-03-28 | 2020-04-05 |  1 | 2020-03-28 | 2020-05-02 | 2020-04-01 |
    |  1 |     30 | 2020-04-21 | 2020-05-02 |  1 | 2020-03-28 | 2020-05-02 | 2020-05-01 |
    |  2 |     20 | 2020-01-28 | 2020-04-05 |  2 | 2020-01-28 | 2020-04-05 | 2020-02-01 |
    |  2 |     20 | 2020-01-28 | 2020-04-05 |  2 | 2020-01-28 | 2020-04-05 | 2020-03-01 |
    |  2 |     20 | 2020-01-28 | 2020-04-05 |  2 | 2020-01-28 | 2020-04-05 | 2020-04-01 |
    +----+--------+------------+------------+----+------------+------------+------------+
  • 相关阅读:
    Vue单页面应用
    MVVM模式理解
    Ajax原生四大步骤
    Vue 全家桶介绍
    原生js的dom操作
    vs2015+opencv3.3.1+ maxflow-v3.01 c++实现Yuri Boykov 的Interactive Graph Cuts
    c++迭代递归实现汉诺塔(5种迭代方法满足你)
    opencv3.3.1+vs2015+c++实现直接在图像上画掩码,保存掩码图片
    声明函数指针、回调函数、函数对象------c++程序设计基础、编程抽象与算法策略
    C++/C语言的标准库函数与运算符的区别new/delete malloc/free
  • 原文地址:https://www.cnblogs.com/chenzechao/p/13044607.html
Copyright © 2011-2022 走看看