【问题标题】:Oracle SQL - Counting entities per day from entity start date and end dateOracle SQL - 从实体开始日期和结束日期开始每天计算实体
【发布时间】:2020-12-14 21:17:48
【问题描述】:

我从这样的表开始:

ENTITY_ID META_ATTRIB_1 META_ATTRIB_2 START_DATE END_DATE
1 FOO BAR 2020-01-01 2020-12-01

我希望每天得到一个属于给定元属性集的实体计数:

DAY META_ATTRIB_1 META_ATTRIB_2 COUNT
2020-01-01 FOO BAR 1
2020-01-02 FOO BAR 1
2020-01-03 FOO BAR 1

现在我通过从DUAL 生成日期序列并通过DAY BETWEEN START_DATE AND END_DATE 加入目标表并按DAY, META_ATTRIB_1, META_ATTRIB_2 分组来执行此操作。

此方法遇到性能问题。是否有更好的方法可以将这些实体行中的每一个拆分到所需的天数序列中,然后将其聚合回来以按天数计算?

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    典型的做法是使用递归在每个范围内每天生成一行,然后聚合:

    with cte (meta_attrib_1, meta_attrib_2, dt, end_date) as (
        select meta_attrib_1, meta_attrib_2, start_date, end_date from mytable
        union all
        select meta_attrib_1, meta_attrib_2, dt + 1, end_date from cte where dt < end_date
    )
    select dt, meta_attrib_1, meta_attrib_2, count(*) as cnt
    from cte
    group by dt, meta_attrib_1, meta_attrib_2
    

    这与您描述的逻辑非常接近。您没有显示您的实际查询,因此很难判断这是否是比您目前正在做的更好的解决方案。

    【讨论】:

      【解决方案2】:

      您可能会发现递归 CTE 更快:

      with cte (day, meta_attrib1, meta_attrib2, end_date)
            select start_date, meta_attrib1, meta_attrib2, end_date
            from t
            union all
            select start_date + interval '1' day, meta_attrib1, meta_attrib2, end_date
            from cte
            where day < end_date
           )
      select day, meta_attrib1, meta_attrib2, count(*)
      from cte
      group by day, meta_attrib1, meta_attrib2;
      

      递归 CTE 的优势在于它“本地化”了日期的扩展。它不依赖非等值连接,而是简单地生成额外的日期。

      这仍然为每个原始行每天生成一个单独的行。这意味着聚合可能是瓶颈。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-08
        • 2019-12-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多