从上一行获取带有delta的最后一个值

时间:2016-08-26 06:59:05

标签: sql postgresql

我有数据

| account | type | position | created_date |
|---------|------|----------|------|
|  1 | 1 | 1 | 2016-08-01 00:00:00 |
|  2 | 1 | 2 | 2016-08-01 00:00:00 |
|  1 | 2 | 2 | 2016-08-01 00:00:00 |
|  2 | 2 | 1 | 2016-08-01 00:00:00 |
|  1 | 1 | 2 | 2016-08-02 00:00:00 |
|  2 | 1 | 1 | 2016-08-02 00:00:00 |
|  1 | 2 | 1 | 2016-08-03 00:00:00 |
|  2 | 2 | 2 | 2016-08-03 00:00:00 |
|  1 | 1 | 2 | 2016-08-04 00:00:00 |
|  2 | 1 | 1 | 2016-08-04 00:00:00 |
|  1 | 2 | 2 | 2016-08-07 00:00:00 |
|  2 | 2 | 1 | 2016-08-07 00:00:00 |

我需要从之前的位置获得最后的职位(账户,类型,职位)和delta。我试图使用Window函数,但只能获取所有行,并且无法对它们进行分组/获取最后一行。

SELECT
    account,
    type,
    FIRST_VALUE(position) OVER w AS position,
    FIRST_VALUE(position) OVER w - LEAD(position, 1, 0) OVER w AS delta,
    created_date
FROM table
WINDOW w AS (PARTITION BY account ORDER BY created_date DESC)

我有结果

| account | type | position | delta | created_date |
|---------|------|----------|-------|--------------|
| 1 | 1 | 1 | 1 | 2016-08-01 00:00:00 |
| 1 | 1 | 2 | 1 | 2016-08-02 00:00:00 |
| 1 | 1 | 2 | 0 | 2016-08-04 00:00:00 |
| 1 | 2 | 2 | 2 | 2016-08-01 00:00:00 |
| 1 | 2 | 1 | -1 | 2016-08-03 00:00:00 |
| 1 | 2 | 2 | 1 | 2016-08-07 00:00:00 |
| 2 | 1 | 2 | 2 | 2016-08-01 00:00:00 |
| 2 | 2 | 1 | 1 | 2016-08-01 00:00:00 |
| and so on |

但我只需要每个帐户/类型对的最后一条记录

| account | type | position | delta | created_date |
|---------|------|----------|-------|--------------|
| 1 | 1 | 2 | 0 | 2016-08-04 00:00:00 |
| 1 | 2 | 2 | 1 | 2016-08-07 00:00:00 |
| 2 | 1 | 1 | 0 | 2016-08-04 00:00:00 |
| and so on |

抱歉我的语言不好,谢谢你的帮助。

1 个答案:

答案 0 :(得分:0)

我的“最好”尝试..

WITH cte_delta AS (
    SELECT
        account,
        type,
        FIRST_VALUE(position) OVER w AS position,
        FIRST_VALUE(position) OVER w - LEAD(position, 1, 0) OVER w AS delta,
        created_date
    FROM table
    WINDOW w AS (PARTITION BY account ORDER BY created_date DESC)
),
cte_date AS (
    SELECT
        account,
        type,
        MAX(created_date) AS created_date
    FROM cte_delta
    GROUP BY account, type
)
SELECT cd.*
FROM
    cte_delta cd,
    cte_date ct
WHERE
    cd.account = ct.account
    AND cd.type = ct.type
    AND cd.created_date = ct.created_date