Oracle首次和最后一次观察多个窗口

时间:2018-06-11 17:45:42

标签: sql oracle

我在Oracle中遇到查询问题。

我的表包含去年的所有贷款申请。一些客户有多个应用程序。我想按如下方式聚合这些应用程序:

对于每个客户,我想在去年找到他的第一个应用程序(让我们称之为A)然后我想找出30天间隔内的最后一个应用程序,从第一个应用程序算起(说B是最后一个)。接下来,我需要在B之后找到应用程序并再次找到30天间隔中的最后一个,如上一步骤。我想要的结果是每个客户的间隔最新和最早的应用程序表。第一个也可能与最后一个相同。

如果没有plsql,我怎么能在Oracle中这样做?这可能吗?我应该使用它的累积时间间隔吗? (但随后每笔金额的起点取决于计算的金额。)

我们假设该表格有以下形式:

application_id (unique) | customer_id (not unique) | create_date
1                         1                          2017-01-02 <- first
2                         1                          2017-01-10 <- middle
3                         1                          2017-01-30 <- last
4                         1                          2017-05-02 <- first and last
5                         1                          2017-06-02 <- first
6                         1                          2017-06-30 <- middle
7                         1                          2017-06-30 <- middle
8                         1                          2017-07-01 <- last

我的期望是:

application_id (unique) | customer_id (not unique) | create_date
1                         1                          2017-01-02 <- first
3                         1                          2017-01-30 <- last
4                         1                          2017-05-02 <- first and last
5                         1                          2017-06-02 <- first
8                         1                          2017-07-01 <- last

提前感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE table_name ( application_id, customer_id, create_date ) AS
SELECT 1, 1, DATE '2017-01-02' FROM DUAL UNION ALL -- <- first
SELECT 2, 1, DATE '2017-01-10' FROM DUAL UNION ALL -- <- middle
SELECT 3, 1, DATE '2017-01-30' FROM DUAL UNION ALL -- <- last
SELECT 4, 1, DATE '2017-05-02' FROM DUAL UNION ALL -- <- first and last
SELECT 5, 1, DATE '2017-06-02' FROM DUAL UNION ALL -- <- first
SELECT 6, 1, DATE '2017-06-30' FROM DUAL UNION ALL -- <- middle
SELECT 7, 1, DATE '2017-06-30' FROM DUAL UNION ALL -- <- middle
SELECT 8, 1, DATE '2017-07-01' FROM DUAL           -- <- last

查询1

WITH data ( application_id, customer_id, create_date, first_date, grp ) AS (
  SELECT t.application_id,
         t.customer_id,
         t.create_date,
         t.create_date,
         1
  FROM table_name t
  WHERE  application_id = 1
UNION ALL
  SELECT t.application_id,
         t.customer_id,
         t.create_date,
         CASE WHEN t.create_date <= d.first_date + INTERVAL '30' DAY
         THEN d.first_date
         ELSE t.create_date
         END,
         CASE WHEN t.create_date <= d.first_date + INTERVAL '30' DAY
         THEN grp
         ELSE grp + 1
         END
  FROM   data d
         INNER JOIN table_name t
         ON (  d.customer_id        = t.customer_id
           AND d.application_id + 1 = t.application_id )
)
SELECT application_id,
       customer_id,
       create_date,
       grp
FROM   (
  SELECT d.*,
         ROW_NUMBER() OVER ( PARTITION BY customer_id, grp ORDER BY create_date ASC  ) AS rn_a,
         ROW_NUMBER() OVER ( PARTITION BY customer_id, grp ORDER BY create_date DESC ) AS rn_d
  FROM   data d
)
WHERE rn_a = 1
OR    rn_d = 1

<强> Results

| APPLICATION_ID | CUSTOMER_ID |          CREATE_DATE | GRP |
|----------------|-------------|----------------------|-----|
|              1 |           1 | 2017-01-02T00:00:00Z |   1 |
|              3 |           1 | 2017-01-30T00:00:00Z |   1 |
|              4 |           1 | 2017-05-02T00:00:00Z |   2 |
|              5 |           1 | 2017-06-02T00:00:00Z |   3 |
|              8 |           1 | 2017-07-01T00:00:00Z |   3 |