2

我有以下格式的数据:

date        fruit
======================
1-jan-14    orange
3-jan-14    orange
1-may-14    orange
2-may-14    apple
3-may-14    apple
1-aug-14    pineapple
2-aug-14    apple

我想添加一个表示:过去 6 个月内购买最多的水果的列。所以,对于上面的例子:

date        fruit       most_purchased_6_months
=======================================
1-jan-14    orange      orange
3-jan-14    orange      orange
1-may-14    orange      orange
2-may-14    apple       orange
3-may-14    apple       orange
1-aug-14    pineapple   apple
2-aug-14    apple       apple

我尝试过使用分析函数,但我所达到的最好的结果是显示过去 6 个月内使用“count(*) over (按日期范围按水果顺序分区 180) 购买相同水果(来自同一行)的次数前)”。

我的主要问题是使用自联接可以轻松解决我的问题,但由于这是一个包含大约 2000 万行数据的表,因此在我们的数据库上运行需要几个小时。将不胜感激任何方向和/或帮助!

4

1 回答 1

1

这是您的基本查询:

select date, fruit,
       count(*) over (partition by fruit order by date range 180 preceding) as NumberPurchased
from data;

我认为您可以使用子查询来做到这一点,并且first_value()

select date, fruit,
       first_value(fruit) over (order by NumberPurchased desc range 180 preceding)
from (select date, fruit,
             count(*) over (partition by fruit order by date range 180 preceding) as NumberPurchased
      from data d
     ) d;

我要留下答案,但上述方法不起作用,因为前六个月每一行的计数都发生了变化。

编辑:

这是一种完全不同的方法。计算每一天和每个水果的累积总和到一个临时表中。然后索引该表并加入它以获得最常见的水果keep

create table FruitCountCume as
    select f.fruit, da.date, count(*) over (partition by f.fruit order by d.date) as cumecnt
    from (select distinct fruit from data) f cross join
         (select distinct date from data) d left outer join
         data da
         on f.fruit = da.fruit and f.date = da.date;

create index on FruitCountCume(fruit, date);

select d1.date, d1.fruit,
       max(fruit) keep (dense_rank first order by d1.cumecnt - coalesce(d2.cumecnt, 0) desc) as MostCommon
from FruitCountCume d1 left outer join
     FruitCountCume d2
     on d1.date = d2.date + 180
group by d1.date;

完全交叉连接可能不是必需的。它的存在是为了left join提高效率。

于 2014-08-24T10:59:21.680 回答