首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PostgreSQL窗口函数

PostgreSQL窗口函数
EN

Stack Overflow用户
提问于 2018-07-06 11:58:53
回答 2查看 81关注 0票数 7

考虑下表结构:

代码语言:javascript
复制
CREATE TABLE tb_log
(
  id INTEGER PRIMARY KEY,
  moment DATE,
  old INTEGER,
  actual INTEGER
);

载有下列数据:

代码语言:javascript
复制
INSERT INTO
  tb_log ( id, moment, old, actual )
VALUES
  ( 1, '2018-06-19', 10, 20 ),
  ( 2, '2018-06-21', 20, 30 ),
  ( 3, '2018-06-25', 30, 40 );

我试图从tb_log获得一个值生效的时间段(开始日期和结束日期)。

试用#1 -使用lag()函数:

代码语言:javascript
复制
SELECT
  lag( moment ) OVER (ORDER BY moment) date_start,
  moment AS date_end,
  old AS period_value
FROM
   tb_log;

它返回以下数据:

代码语言:javascript
复制
| date_start |   date_end | period_value |
|------------|------------|--------------|
|     (null) | 2018-06-19 |           10 |
| 2018-06-19 | 2018-06-21 |           20 |
| 2018-06-21 | 2018-06-25 |           30 |

试用#2 -使用lead()函数:

代码语言:javascript
复制
SELECT
  moment AS date_start,
  lead( moment ) OVER (ORDER BY moment) date_end,
  actual AS period_value
FROM
   tb_log;

它返回以下数据:

代码语言:javascript
复制
| date_start |   date_end | period_value |
|------------|------------|--------------|
| 2018-06-19 | 2018-06-21 |           20 |
| 2018-06-21 | 2018-06-25 |           30 |
| 2018-06-25 |     (null) |           40 |

SQLFiddle.com

是否有任何使用Window Functions返回如下内容的技巧:

代码语言:javascript
复制
| date_start |   date_end | period_value |
|------------|------------|--------------|
|     (null) | 2018-06-19 |           10 |
| 2018-06-19 | 2018-06-21 |           20 |
| 2018-06-21 | 2018-06-25 |           30 |
| 2018-06-25 |     (null) |           40 |

有什么想法吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-07-06 12:33:27

没有使用窗口函数的诀窍,因为窗口函数不会向数据中添加一行。在我看来,使用lead()要自然得多

代码语言:javascript
复制
(SELECT moment, lead(moment) over (order by moment) as date_end,
       actual AS period_value
 FROM tb_log
)
UNION ALL
(SELECT null, moment, old
 FROM tb_log
 ORDER BY moment
 LIMIT 1
);

一般来说,使用union all而不是union是个好主意。Union会导致删除重复项的开销。

票数 6
EN

Stack Overflow用户

发布于 2018-07-06 12:07:07

代码语言:javascript
复制
    SELECT
      lag( moment ) OVER (ORDER BY moment) date_start,
      moment AS date_end,
      old AS period_value
    FROM
       tb_log
    union
    SELECT
      moment AS date_start,
      lead( moment ) OVER (ORDER BY moment) date_end,
      actual AS period_value
    FROM
       tb_log
order by 3;
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51210006

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档