吸引到期后续订软件包的用户

时间:2019-06-16 11:51:16

标签: sql sql-server

我有一个表,其中提供了有关哪些用户购买了软件包,软件包何时启动,过期等信息。

表:

+------+--------------+------------+------------+---------+
| user | Package_Type |   Start    |    End     | Status  |
+------+--------------+------------+------------+---------+
|  111 | A            | 2019-06-01 | 2019-06-18 | Valid   |
|  123 | A            | 2019-06-01 | 2019-06-18 | Valid   |
|  124 | A            | 2019-06-02 | 2019-06-06 | Expired | //Type A expired
|  124 | C            | 2019-06-02 | 2019-06-18 | Valid   |
|  125 | B            | 2019-06-03 | 2019-06-09 | Expired |
|  126 | B            | 2019-06-04 | 2019-06-20 | Valid   |
|  127 | B            | 2019-06-04 | 2019-06-07 | Expired |  // Type B expired
|  124 | B            | 2019-06-06 | 2019-06-18 | Valid   |  //Renewal to type B after expiry of type A
|  127 | B            | 2019-06-08 | 2019-06-18 | Valid   |  // Renwal to Type B
+------+--------------+------------+------------+---------+

在一个时间范围(将时间范围设为WHERE start BETWEEN '2019-06-01' AND '2019-06-10'中,我想知道有多少用户的软件包过期了。

预期输出如下

+------------+---------+---------+
|    Date    | Expired | Renewed |
+------------+---------+---------+
| 2019-06-01 |       0 |       0 |
| 2019-06-02 |       0 |       0 |
| 2019-06-03 |       0 |       0 |
| 2019-06-04 |       0 |       0 |
| 2019-06-05 |       0 |       0 |
| 2019-06-06 |       1 |       1 | // Expiry and renewal of user 124
| 2019-06-07 |       1 |       0 | // Expiry of user 127
| 2019-06-08 |       0 |       1 |//  Renewal of user 127
| 2019-06-09 |       1 |       0 |// Expiry of user 125
| 2019-06-10 |       0 |       0 |
+------------+---------+---------+

用户不必续签相同类型的软件包。

  1. 对于用户124,类型A已过期,但他已续签为类型B。(还请注意,用户124对于类型C仍处于活动状态)。
  2. 因此,在某些情况下,某种类型的软件包会过期,但是同一用户可以在其他软件包上处于活动状态,并且可以续签到其他软件包本身。
  3. 我只想知道软件包到期后用户何时续订(即使他在其他任何软件包上都处于活动状态)

更新1 我还希望将以上数据表示为

+--------------+---------+---------+
| Package_Type | Expired | Renewed |
+--------------+---------+---------+
| A            |       1 |       0 |
| B            |       2 |       2 |
| C            |       0 |       0 |
+--------------+---------+---------+

我想要一个查询,如果我更改 WHERE start BETWEEN '2019-06-01' AND '2019-06-10')*

上表将根据start过滤器进行更新

SQL Server Link

1 个答案:

答案 0 :(得分:1)

您可以使用累积的max()来获取续订的用户:

select t1.*,
       (case when max(case when status = 'expired' then [start] end) over (partition by user order by [start]) < [start] and
                  status = 'Valid'
             then 1 else 0
        end) as renewed
from table1 t1;

然后您可以使用此信息来汇总数据。但是,这种总结是相当棘手的。续订是在开始日期算起的,而到期是在到期日期。为了解决这个问题,它使用apply取消数据透视。

select dte, sum(is_expire), sum(is_renew)
from (select t1.*,
             (case when max(case when status = 'expired' then [start] end) over (partition by user order by [start]) < start and
                        status = 'Valid'
                   then 1 else 0
              end) as renewed
      from table1 t1
     ) t1 cross apply
     (values (start, 0, renewed),
             ([end], case when status = 'expired' then 1 else 0 end, 0)
     ) v(dte, is_expire, is_renew)
group by dte
order by dte;

Here是一个SQLFiddle。