前 7 天销售

First 7 days sales

我想查看某件商品自销售第一天起 7 天内的金额总和。基本上,我想查看前 7 天的销售额总和。

我正在使用以下查询。

select item, sum(amt)
from table
where first_sale_dt = (first_sale_dt + 6).

当我运行这个查询时,我没有得到任何结果。

你的代码目前不会给你任何结果,因为你正在查看每一行,并且询问值 first_sale_dt 是否等于它不是 +6[=21= 的值]

您需要使用 WINDOW 函数来查看许多行,或者自行加入 table 并过滤连接的行以提供您想要的结果。

所以用数据的CTE进行测试:

WITH data as (
    select * from values
    (1, 2,  '2022-03-01'::date),
    (1, 4,  '2022-03-04'::date),
    (1, 200,'2022-04-01'::date),
    (3, 20, '2022-03-01'::date)
    t(item, amt, first_sale_dt)
)

这个 SQL 显示我们想要求和的筛选行,它使用 sub-select(可以移到 CTE 中)找到要执行的“首次销售”的日期范围。

select a.item, b.amt
from (
    select 
        item, 
        min(first_sale_dt) as first_first_sale_dt 
    from data
    group by 1
    ) as a
join data as b
   on a.item = b.item  and b.first_sale_dt <= (a.first_first_sale_dt + 6)
ITEM AMT
1 2
1 4
3 20

因此添加了 SUM:

select a.item, sum(b.amt)
from (
    select 
        item, 
        min(first_sale_dt) as first_first_sale_dt 
    from data
    group by 1
    ) as a
join data as b
   on a.item = b.item  and b.first_sale_dt <= (a.first_first_sale_dt + 6)
group by 1;

你得到:

ITEM SUM(B.AMT)
1 6
3 20

滑动Window:

这依赖于密集数据(每天 1 行),而且滑动 WINDOW 正在做的工作正在被丢弃,这是一个字符串标志,这不是高性能的解决方案,我会坚持第一个解决方案。

WITH data as (
    select * from values
    (1, 2,  '2022-03-01'::date),
    (1, 2,  '2022-03-02'::date),
    (1, 2,  '2022-03-03'::date),
    (1, 2,  '2022-03-04'::date),
    (1, 2,  '2022-03-05'::date),
    (1, 2,  '2022-03-06'::date),
    (1, 2,  '2022-03-07'::date),
    (1, 2,  '2022-03-08'::date)
    t(item, amt, first_sale_dt)
)
select item,
    first_sale_dt,
    sum(amt) over(partition by item order by first_sale_dt rows BETWEEN current row and 6 following ) as s
    ,count(amt) over(partition by item order by first_sale_dt rows BETWEEN current row and 6 following ) as c
from  data
order by 2;
ITEM FIRST_SALE_DT S C
1 2022-03-01 14 7
1 2022-03-02 14 7
1 2022-03-03 12 6
1 2022-03-04 10 5
1 2022-03-05 8 4
1 2022-03-06 6 3
1 2022-03-07 4 2
1 2022-03-08 2 1

因此您需要过滤掉一些行。

WITH data as (
    select * from values
    (1, 2,  '2022-03-01'::date),
    (1, 2,  '2022-03-02'::date),
    (1, 2,  '2022-03-03'::date),
    (1, 2,  '2022-03-04'::date),
    (1, 2,  '2022-03-05'::date),
    (1, 2,  '2022-03-06'::date),
    (1, 2,  '2022-03-07'::date),
    (1, 2,  '2022-03-08'::date)
    t(item, amt, first_sale_dt)
)
select item,
    sum(amt) over(partition by item order by first_sale_dt rows BETWEEN current row and 6 following ) as s
from  data
qualify row_number() over (partition by item order by first_sale_dt) = 1

给出:

ITEM S
1 14

如果你真的要用window function。这是初学者友好的版本

with cte as 
    
(select *, min(sale_date) over (partition by item) as sale_start_date 
 from data) --thanks Simeon
        
select item, sum(amt) as amount
from cte
where sale_date <= sale_start_date + 6 --limit to first week
group by item;

附带说明一下,我建议在日期

上使用 dateadd 而不是 +