该表由以下脚本表示:

CREATE TABLE sales (
  id SERIAL PRIMARY KEY,
  product_id INTEGER,
  sales_date DATE,
  quantity INTEGER,
  price NUMERIC
);

INSERT INTO sales (product_id, sales_date, quantity, price) VALUES
   (1, '2023-01-01', 10, 10.00),
   (1, '2023-01-02', 12, 12.00),
   (1, '2023-01-03', 15, 15.00),
   (2, '2023-01-01', 8, 8.00),
   (2, '2023-01-02', 10, 10.00),
   (2, '2023-01-03', 12, 12.00);

任务是对每个产品_id过go 3天的销售数量进行总和.该期间必须从每个产品_id的最大(最后)日期起向后计数.因此,对于1来说,最大值是2023-01-03,对于2来说也是如此.但对于产品_id 2,最后一天可能与1不同-假设是2023-01-05.

通过在子查询中应用具有窗口功能的此查询:

select product_id, max(increasing_sum) as quantity_last_3_days
   from 
        (SELECT product_id,
         SUM(quantity) OVER (PARTITION BY product_id ORDER BY sales_date RANGE BETWEEN INTERVAL '2 days'
                PRECEDING AND CURRENT ROW) AS increasing_sum
         FROM sales) as s
   group by product_id;

我收到预期输出:

  | product_id | quantity_last_3_days |
  |____________|______________________|            
  |_____1______|___________37_________|
  |_____2______|___________30_________|     
 

但这是最佳解决方案吗?有什么方法可以通过使用不带子查询的窗口函数来解决这个问题吗?

推荐答案

但这是最佳解决方案吗?

不,如果你只需要"to sum sales 100 for last 3 days per each 101"就不会了.

有什么方法可以通过使用不带子查询的窗口函数来解决这个问题吗?

您通常可以将窗口函数换成相关子查询、lateral或纯量,但有一种更简单的方法可以加快您的查询并更正它.它正在做额外的工作,试图为您获取滚动/步进总和;窗口并不是试图获取每个product_id的最近3天.

相反,对于每一行,它都会回顾2天前具有相同product_id的行.您稍后 Select 总和最高的3天期间quantity,这不一定是最近的3个日期.

在40万个样本上,您的查询在没有索引的情况下需要整个1.0s,在有a covering index的情况下需要0.7s,您可以从这个数字下降到没有索引的0.4s或在有覆盖索引的情况下需要0.1s.您只需询问每个product_id:demo at db<>fiddle最近3个日期的总和

select product_id,sum(quantity) as quantity_last_3_days
from(select *,row_number()over(PARTITION BY product_id ORDER BY sales_date DESC)
     from sales)_
where 3>=row_number
group by product_id;

The trick here is that the window function will execute with a Run Condition: (3 >= row_number() OVER (?)), which means it'll just grab the 3 most recent and quit. It can even get them straight off the top of the covering index, without ever having to visit the table.
Your original query has to scan the whole thing (either the entire table or the whole index, if it's available), then sort that to get the max().

Sql相关问答推荐

如何重用表值用户定义函数调用的结果?

转换表中的数据

提高写密集型表的查询性能

PostgreSQL中的合并命令是原子的,还是需要一些类似于SQL Server版本的内容?

每组显示一行(表1中的分组值),表2中的不同列表用逗号分隔

PostgreSQL:使用JSONB中的字段使用jsonb_to_Records()填充记录

UPDATE查询中的乐观锁

了解放置时的连接

将日期时间转换为日期格式

如何使用SQL Server中的Nodes()方法执行与OPENXML相同的操作

在查询Oracle SQL中创建替代ID

将一个数组反嵌套到另外两个数组SQL中(Athena/presto)

根据是否出现过零来筛选数据(跨多行)

PATINDEX中与[A-Z]匹配(U除外)的正则表达式

最小非重复集的SQL查询

Netezza SQL:判断两个表是否相同

给定 3 个键列,从一个表中 Select 另一表中不存在的所有数据

带聚合函数的 percentile_cont

在 SQL 中使用循环遍历按时间顺序排列的数据

在多个表上递归查找