标签: window-functions

如何在 PostgreSQL 中获取分区(窗口)的大小?

使用窗口时,如何获取当前分区的大小(行数)?

例如,假设我有一个表,其中包含博客中帖子的评论。我想知道每个帖子的第一条评论、第二条评论、最后一条评论和评论数是什么(没有另一个子查询,我按 post 和 do 分组COUNT(*))。

查询应类似于:

SELECT DISTINCT
    post_id.
    first_value(comment_text) OVER wnd AS first_comment,
    nth_value(comment_text, 2) OVER wnd AS second_comment,
    last_value(comment_text) OVER wnd AS last_comment,
    SOME_FUNCTION(comment_text) OVER wnd AS number_of_comments
FROM comments
WINDOW wnd AS (
    PARTITION BY post_id
    ORDER BY comment_created_at ASC
    ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
);
Run Code Online (Sandbox Code Playgroud)

应该SOME_FUNCTION是什么?

sql postgresql window-functions

6
推荐指数
1
解决办法
960
查看次数

窗口函数:在 ORDER BY 另一列之后的 PARTITION BY

免责声明:显示的问题比我最初预期的要普遍得多。下面的例子取自另一个问题的解决方案。但是现在我正在使用这个示例来解决更多问题 - 主要与时间序列有关(查看右侧栏中的“链接”部分)。

所以我想先更一般地解释这个问题:


我正在使用 PostgreSQL,但我确信这个问题也存在于其他支持 DBMS 的窗口函数(MS SQL Server、Oracle 等)中。


窗口函数可用于通过公共属性或值将某些值组合在一起。例如,您可以按日期对行进行分组。然后您可以计算每个日期内的最大值或平均值或计数行或其他任何内容。

这可以通过定义一个PARTITION. 按日期分组将适用于PARTITION BY date_column. 现在,您想要在您的组中执行一个需要特殊顺序的操作(计算行号或对列求和)。这可以通过PARTITON BY date_column ORDER BY an_attribute_column.

现在考虑更精细的时间序列分辨率。如果您没有日期但有时间戳怎么办。然后你不能再按时间列分组。但是,按添加顺序分析数据可能很重要(也许时间戳是数据集的创建时间)。然后您意识到一些连续的行具有相同的值,并且您希望按此公共值对数据进行分组。但线索是行有不同的时间戳。

这里的问题是你不能做一个PARTITION BY value_column. 因为先PARTITION BY强制排序。因此,您的表将按value_column分组前排序,不再按时间戳排序。这会产生您意想不到的结果。

更一般地说:问题是即使有序列不是创建的分区的一部分,也要确保特殊排序


例子:

数据库<>小提琴

我有下表:

ts      val
100000  50
130100  30050
160100  60050 
190200  100
220200  30100 
250200  30100 
300000  300
500000  100
550000  1000  
600000  1000
650000  2000  
700000  2000
720000  2000
750000  300
Run Code Online (Sandbox Code Playgroud)

我有一个问题,我必须对列的所有绑定值进行分组val …

sql postgresql window-functions

6
推荐指数
1
解决办法
1632
查看次数

Pyspark 窗口函数在其他列上带有过滤器

我有一个 pyspark 数据框,其中包含以下数据:

| y | date       | amount| id |
 ----------------------------- 
| 1 | 2017-01-01 | 10    | 1  |
| 0 | 2017-01-01 | 2     | 1  |
| 1 | 2017-01-02 | 20    | 1  |
| 0 | 2017-01-02 | 3     | 1  |
| 1 | 2017-01-03 | 2     | 1  |
| 0 | 2017-01-03 | 5     | 1  |
Run Code Online (Sandbox Code Playgroud)

我想应用窗口函数,但sum仅应用聚合函数 y==1 的列,但仍保留其他列。我要应用的窗口是:

w = Window \
        .partitionBy(df.id) \
        .orderBy(df.date.asc()) \
        .rowsBetween(Window.unboundedPreceding, …
Run Code Online (Sandbox Code Playgroud)

window-functions apache-spark apache-spark-sql pyspark

6
推荐指数
1
解决办法
4714
查看次数

dplyr 相当于 sql row_number() over(按值按组顺序分区)

初始情况

我有以下形式的数据集:

library(dplyr)

dat <- tribble(
  ~name, ~iq,
  "ben",  100,
  "alex",  98,
  "mia",  110,
  "paco", 124,
  "mia",  112,
  "mia",  120,
  "paco", 112,
  "ben",   90,
  "alex", 107
)
Run Code Online (Sandbox Code Playgroud)

我想创建一个新列,按降序name对值iq进行排序和分组。在 SQL 中可以写

select
  name,
  iq,
  row_number() over (partition by name order by iq desc) as rank
from
  dat;
Run Code Online (Sandbox Code Playgroud)

这将产生以下预期输出(为简单起见已排序):

library(dplyr)

dat <- tribble(
  ~name, ~iq,
  "ben",  100,
  "alex",  98,
  "mia",  110,
  "paco", 124,
  "mia",  112,
  "mia",  120,
  "paco", 112,
  "ben",   90,
  "alex", 107
)
Run Code Online (Sandbox Code Playgroud)

问题

使用我的数据,可以通过以下方式获得所需的结果:

dat %>% …
Run Code Online (Sandbox Code Playgroud)

r window-functions dplyr

6
推荐指数
0
解决办法
3274
查看次数

如何将时间戳分组为岛(基于任意间隙)?

将此日期列表视为timestamptz

Postgres 分组日期

我使用颜色手动对日期进行分组:每组与下一组之间至少有 2 分钟的间隔。

我试图通过查看给定用户何时执行某项操作(数据是他们完成学习一个句子时的数据)来衡量给定用户的学习量。例如:在黄色块上,我认为用户一次性学习了,从 14:24 到 14:27,或者连续大约 3 分钟。

我了解如何通过遍历所有日期并查找两行之间的间隙,使用编程语言对这些日期进行分组。

我的问题是:如何使用 Postgres 以这种方式对日期进行分组?

(在 Google 或 SO 上寻找“差距”会带来太多不相关的结果;我想我错过了我在这里尝试做的事情的词汇。)

sql postgresql time-series window-functions gaps-and-islands

6
推荐指数
1
解决办法
1082
查看次数

如何理解前两行和当前行之间的行结果?

我的 SQL 查询是:

SELECT time, buy,
  avg(buy) OVER (ORDER BY time rows between 1 preceding and current row) as average_2,
  avg(buy) OVER (ORDER BY time rows between 2 preceding and current row) as average_3
FROM my_table; 
Run Code Online (Sandbox Code Playgroud)

我试图理解这些窗口函数。我使用了一些测试数据并得到了结果:

TIME                       BUY  AVERAGE_2  AVERAGE_3
------------------- ---------- ---------- ----------
2019-05-05 10:05:19          1          1          1
2019-05-05 10:05:22          2        1.5        1.5
2019-05-05 10:05:25          3        2.5          2
2019-05-05 10:05:27          4        3.5          3
Run Code Online (Sandbox Code Playgroud)

我需要知道:如何获得这些结果?特别是average_3

ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW和 和有什么区别rows between 2 …

sql oracle window-functions

6
推荐指数
2
解决办法
1万
查看次数

如何在 PostgreSQL 中使用 LAST_VALUE?

我有一个小表格来尝试了解该LAST_VALUE函数在 PostgreSQL 中的工作原理。它看起来像这样:

 id | value
----+--------
  0 | A
  1 | B
  2 | C
  3 | D
  4 | E
  5 | [null]
  6 | F
Run Code Online (Sandbox Code Playgroud)

我想要做的是使用LAST_VALUE先行的非NULL值来填充NULL值,所以结果应该是这样的:

 id | value
----+--------
  0 | A
  1 | B
  2 | C
  3 | D
  4 | E
  5 | E
  6 | F

Run Code Online (Sandbox Code Playgroud)

我试图完成的查询是:

SELECT LAST_VALUE(value)
OVER (PARTITION BY id ORDER BY case WHEN value IS NULL THEN 0 ELSE 1 END ASC)
FROM test; …
Run Code Online (Sandbox Code Playgroud)

sql postgresql window-functions

6
推荐指数
2
解决办法
4134
查看次数

postgres 查询中的多个命名窗口

postgres 文档指定了一个窗口定义子句:

[ WINDOW window_name AS ( window_definition ) [, ...] ]
Run Code Online (Sandbox Code Playgroud)

[ ,...]指定可以有多个窗口。我在文档中找不到任何其他内容来确认或否认这是可能的。我该如何进行这项工作?

在此查询中,我可以单独使用任一窗口子句,但即使语法遵循规范,我也不能同时使用两者:

[ WINDOW window_name AS ( window_definition ) [, ...] ]
Run Code Online (Sandbox Code Playgroud)

我可以通过不使用窗口定义来获得技术效果,但是对于重复使用窗口的复杂查询来说,这会变得令人厌烦:

select q.*
, min(value) over w_id as min_id_val
--, min(value) over w_kind as min_kind_val
from (
    select 1 as id, 1 as kind, 3.0 as value
    union select 1, 2, 1.0
    union select 2, 1, 2.0
    union select 2, 2, 0.5
) as q
window w_id as (partition by id)
-- , …
Run Code Online (Sandbox Code Playgroud)

postgresql window-functions

6
推荐指数
1
解决办法
1659
查看次数

sql 在子集中创建序列号 - apache derby

能够使用以下查询生成序列号

CREATE SEQUENCE seqno AS integer
START WITH 1;

SELECT t1.*,
   (NEXT VALUE
    FOR seqno) AS seqno
FROM
  (SELECT l.TRANSACTION_ID,
      l.HSN
   FROM RWLINEITEM l
   WHERE l.TRANSACTION_ID IN ('CS610-20-10003','CS610-20-10002')
   GROUP BY l.TRANSACTION_ID,l.HSN) t1
Run Code Online (Sandbox Code Playgroud)

这给出了结果

sql 输出

要求是通过 Transaction 和 HSN 生成序列号,例如

预期结果

有什么办法可以达到这个结果。使用 derby-10.13.1.1

sql derby window-functions

6
推荐指数
1
解决办法
122
查看次数

pyspark 时间序列数据的高性能滚动/窗口聚合

基本问题

我有一个大约有 100 亿行的数据集。我正在寻找最高效的方法来计算四个不同时间窗口(3 天、7 天、14 天、21 天)内的滚动/窗口聚合/指标(总和、平均值、最小值、最大值、stddev)。

Spark/AWS EMR 规格

Spark 版本:2.4.4
ec2 实例类型:r5.24xlarge
核心 ec2 实例数量:10
pyspark 分区数量:600

概述

我读了一堆 SO 帖子,这些帖子要么解决了计算滚动统计的机制,要么解决了如何使窗口函数更快。然而,没有一篇文章以解决我的问题的方式结合这两个概念。我在下面显示了一些选项,它们可以完成我想要的操作,但我需要它们在我的真实数据集上运行得更快,因此我正在寻找更快/更好的建议。

我的数据集的结构如下,但约有 100 亿行:

+--------------------------+----+-----+
|date                      |name|value|
+--------------------------+----+-----+
|2020-12-20 17:45:19.536796|1   |5    |
|2020-12-21 17:45:19.53683 |1   |105  |
|2020-12-22 17:45:19.536846|1   |205  |
|2020-12-23 17:45:19.536861|1   |305  |
|2020-12-24 17:45:19.536875|1   |405  |
|2020-12-25 17:45:19.536891|1   |505  |
|2020-12-26 17:45:19.536906|1   |605  |
|2020-12-20 17:45:19.536796|2   |10   |
|2020-12-21 17:45:19.53683 |2   |110  |
|2020-12-22 17:45:19.536846|2   |210  |
|2020-12-23 17:45:19.536861|2   |310  |
|2020-12-24 17:45:19.536875|2   |410 …
Run Code Online (Sandbox Code Playgroud)

window-functions apache-spark apache-spark-sql rolling-computation pyspark

6
推荐指数
1
解决办法
8717
查看次数