【问题标题】:Storing weekly and monthly aggregates in Oracle在 Oracle 中存储每周和每月的聚合
【发布时间】:2012-01-22 22:14:38
【问题描述】:

我需要动态更新每个产品和客户的每周和每月销售数据。这些需要在产品销售期间更新和检查,由于各种原因,我无法为此使用存储过程或物化视图(我会将所有内容读入应用程序,修改内存中的所有内容,然后更新和提交结果)。

在一段时间内保存销售的最佳表结构是什么?

  • 存储带有开始和结束日期的期间类型(M、W),还是只存储类型和开始日期?
  • 使用日期字段和字符,或将其编码为字符串('M201201' / 'W201248')
  • 将销售额和期间标准化到两个表中,还是将销售额和期间保留在一个表中?

我将进行两种查询 - 选择当前每周(异或每月)期间/客户/文章的销售额但不更新它们,并选择更新客户/文章的每周和每月期间。

【问题讨论】:

    标签: oracle database-design oracle9i


    【解决方案1】:

    如果您将适用期间的开始日期和结束日期都存储在行中,那么您的检索查询会容易得多,至少是基于单个日期(如今天)的检索查询。这是一种非常典型的访问模式,因为您可能会从给定日期发生的商业交易(如特定销售)的角度来看待事物。

    where @date_of_interest >= start_date and @date_of_interest <= end_date很直接也很简单。任何其他组合都要求您在进行查询之前在代码中或在查询本身中进行日期运算。

    保留类型代码(M、W)以及开始和结束日期需要引入一些冗余。但是,为了简化数据检索,您可能会选择引入这种冗余。这个:where @date_of_interest >= start_date and @date_of_interest <= end_date and range_type='M'也很直接很简单。

    与所有非规范化一样,您需要确保拥有能够管理这种冗余的控件。

    【讨论】:

    • 谢谢,关于日期算术的要点——这也是我最初关心的问题。不幸的是,我无法避免它,因为我必须在创建条目时输入正确的日期 - 由于我们的 ORM 框架,我不能简单地使用 TRUNC(@date_of_interest,'IW')。
    【解决方案2】:

    我建议您为此目的使用规范化架构,将每周和每月聚合存储在具有相同结构的两个不同表中。我不知道您要执行哪种查询,但我想这会使进行任何类型的搜索变得更容易(如果以正确的方式完成!!!)。

    可能类似于这个示例

    product_prices (
        prod_code,
        price,
        date_price_begin
    );
    
    sales (
        prod_code,
        customer_code,
        sale_date
    );
    
    
    <aggregate-week>
    select trunc(sale_date,'w') as week,
        prod_code,
        customer_code,
        sum(price) keep (dense_rank first order by date_price_start) as price
    from sales 
        natural join product_prices
    where sale_date > date_from
    group by trunc(sale_date,'iw'),
        prod_code,
        customer_code
    /
    
    <aggregate-month>
    select trunc(sale_date,'m') as month,
        prod_code,
        customer_code,
        sum(price) keep (dense_rank first order by date_price_start) as price
    from sales 
        natural join product_prices
    where sale_date > date_from
    group by trunc(sale_date,'m'),
        prod_code,
        customer_code
    /
    

    【讨论】:

    • 我无法进行实际的 sql 聚合,我尝试了一次(使用视图),但速度不够快(我必须检查每个订单行的聚合销售数据)。另外,我感兴趣的是整个期间售出的实际件数,而不是该期间的价格。使用两张表,而不是一张带有索引的表,甚至是一张带有两个分区的单张表有什么好处?
    • 我无法想象这些查询怎么会这么慢!!他们使用的表不会那么大(每行少于 50 个字节)并且聚合表可以增量构建(通过在每周/月末添加新行)。无论如何,我会测试这个案例,我会用结果更新我的帖子。
    • 我想你误会了,一周结束后我不需要每周汇总,我在一周内需要它(作为库存的一部分)。这意味着当我在星期三 13:45 为客户 100000 处理产品 123456 的销售时,我需要从星期一 00:00 到星期三交易开始的商品的总销售额。如果每次我想向客户销售产品时,我都必须对销售数据执行“SELECT .. GROUP BY”,那么数据库将无法跟上。这就是为什么我必须在每次销售后对聚合进行增量更新。
    猜你喜欢
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-15
    相关资源
    最近更新 更多