python - 加入两个时间序列的最有效方法

标签 python sql postgresql amazon-redshift

假设我有一个这样的表:

 CREATE TABLE time_series (
        snapshot_date DATE,
        sales INTEGER,
PRIMARY KEY (snapshot_date));

具有这样的值:

INSERT INTO time_series SELECT '2017-01-01'::DATE AS snapshot_date,10 AS sales;
INSERT INTO time_series SELECT '2017-01-02'::DATE AS snapshot_date,4 AS sales;
INSERT INTO time_series SELECT '2017-01-03'::DATE AS snapshot_date,13 AS sales;
INSERT INTO time_series SELECT '2017-01-04'::DATE AS snapshot_date,7 AS sales;
INSERT INTO time_series SELECT '2017-01-05'::DATE AS snapshot_date,15 AS sales;
INSERT INTO time_series SELECT '2017-01-06'::DATE AS snapshot_date,8 AS sales;

我希望能够做到这一点:

SELECT a.snapshot_date, 
       AVG(b.sales) AS sales_avg,
       COUNT(*) AS COUNT
  FROM time_series AS a
  JOIN time_series AS b
       ON a.snapshot_date > b.snapshot_date
 GROUP BY a.snapshot_date

产生这样的结果:

*---------------*-----------*-------*
| snapshot_date | sales_avg | count |
*---------------*-----------*-------*
|  2017-01-02   |   10.0    |    1  |
|  2017-01-03   |   7.0     |    2  |
|  2017-01-04   |   9.0     |    3  |
|  2017-01-05   |   8.5     |    4  |
|  2017-01-06   |   9.8     |    5  |
-------------------------------------

对于少量的行,就像在这个例子中,查询运行得非常快。问题是我必须对数百万行执行此操作,并且在 Redshift(语法类似于 Postgres)上我的查询需要几天才能运行。它慢得可怕,但这是我最常用的查询模式之一。我怀疑问题是由于数据中的 O(n^2) 与更可取的 O(n) 的增长有关。

我在 python 中的 O(n) 实现是这样的:

rows = [('2017-01-01',10),
        ('2017-01-02',4),
        ('2017-01-03',13),
        ('2017-01-04',7),
        ('2017-01-05',15),
        ('2017-01-06',8)]
sales_total_previous = 0
count = 0
for index, row in enumerate(rows):
    snapshot_date = row[0]
    sales = row[1]
    if index == 0:
        sales_total_previous += sales
        continue
    count += 1
    sales_avg = sales_total_previous / count
    print((snapshot_date,sales_avg, count))
    sales_total_previous += sales

结果如下(与 SQL 查询相同):

('2017-01-02', 10.0, 1)
('2017-01-03', 7.0, 2)
('2017-01-04', 9.0, 3)
('2017-01-05', 8.5, 4)
('2017-01-06', 9.8, 5)

我正在考虑切换到 Apache Spark,这样我就可以执行那个 python 查询,但是几百万行并不是真的那么大(最多 3-4 GB)并且使用 Spark 集群有 100 GB RAM 似乎矫枉过正。有没有一种有效且易于阅读的方法可以在 SQL 中获得 O(n) 效率,最好是在 Postgres/Redshift 中?

最佳答案

你似乎想要:

SELECT ts.snapshot_date, 
       AVG(ts.sales) OVER (ORDER BY ts.snapshot_date) AS sales_avg,
       ROW_NUMBER() OVER (ORDER BY ts.snapshot_date) AS COUNT
FROM time_series ts;

您会发现使用窗口函数效率更高。

关于python - 加入两个时间序列的最有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48103964/

相关文章:

python - 我的计数器运行不正常

python - 对数对数图中的寄生虫 x Axis

sql - Oracle 批量收集问题

java - 在intellij中使用java连接到数据库(postgres)

python - 使用 python 函数输出更新单个 postgresql 行

sql - 使用 "select trim"时如何避免postgresql更改列名

python - 查找列表的最小值并从另一个列表中打印相应的索引

python - python中的链接检查器

java - 实体管理器在 native 查询调用结束之前不回答

postgresql - 具有随机排序行的可重复分页