【问题标题】:History records, missing records, filling in the blanks历史记录、缺失记录、填空
【发布时间】:2010-01-15 14:44:22
【问题描述】:

我有一个表格,其中包含按地点划分的成本历史记录。这些每月更新一次。 例如

Location1, $500, 01-JAN-2009
Location1, $650, 01-FEB-2009
Location1, $2000, 01-APR-2009

如果我查询 3 月 1 日,我想返回 2 月 1 日的值,因为 3 月 1 日不存在。 我已经使用 oracle 分析编写了一个查询,但这需要花费太多时间(对于报告来说这很好,但我们使用它来允许用户通过前面和切换日期直观地查看数据,重新查询需要太长,只要表是 100 万行)。 所以,我的下一个想法是简单地用丢失的数据更新表。在上述情况下,我只需添加一条与 01-FEB-2009 相同的记录,只是将日期设置为 01-MAR-2009。

我想知道你们是否都想过如何最好地做到这一点。 我的计划是简单地为一个位置创建一个游标,获取第一条记录,然后获取下一条记录,如果下一条记录不是下个月的,则插入缺失月份的记录。

更多信息:

CREATE TABLE MAXIMO.FCIHIST_BY_MONTH
(
  LOCATION     VARCHAR2(8 BYTE),
  PARKALPHA    VARCHAR2(4 BYTE),
  LO2          VARCHAR2(6 BYTE),
  FLO3         VARCHAR2(1 BYTE),
  REGION       VARCHAR2(4 BYTE),
  AVG_DEFCOST  NUMBER,
  AVG_CRV      NUMBER,
  FCIDATE      DATE
)

然后是我正在使用的查询(系统将传递日期和 parkalpha)。该表大约有 100 万行,同样,虽然报告需要相当长的时间,但交互式显示需要的时间太长了

select location, avg_defcost, avg_crv, fcimonth, fciyear,fcidate from
(select location, avg_defcost, avg_crv, fcimonth, fciyear, fcidate,
max(fcidate) over (partition by location) my_max_date 
from FCIHIST_BY_MONTH 
where fcidate <='01-DEC-2008'
and parkalpha='SAAN'
)
where fcidate=my_max_date;

【问题讨论】:

  • 顺便说一句,我修复了我的索引,现在它运行得非常快。当然,他们现在正在改变要求,所以......

标签: oracle plsql


【解决方案1】:

最好的方法是创建一个 PL/SQL 存储过程,该过程从现在开始向后工作,并运行无法返回数据的查询。每个月如果它未能返回数据,它就会为丢失的数据插入一行。

create or replace PROCEDURE fill_in_missing_data IS
  cursor have_data_on_date is
    select locaiton, trunc(date_filed) have_date
    from the_table
    group by location, trunc(date_field)
    order by desc 1
  ;  
  a_date date;
  day_offset number;
  n_days_to_insert number;
BEGIN
   a_date := trunc(sysdate);
   for r1 in fill_in_missing_data loop
     if r1.have_date < a_date then
       -- insert dates in a loop
       n_days_to_insert := a_date - r1.have_date; -- Might be off by 1, need to test.
       for day_offset in 1 .. n_days_to_insert loop
         -- insert missing day
         insert into the_table ( location, the_date, amount ) 
            values ( r1.location, a_date-day_offset, 0 );
       end loop;
     end if; 
     a_date := r1.have_date;
     -- this is a little tricky - I am going to test this and update it in a few minutes
   end loop;
END;

【讨论】:

    【解决方案2】:

    填写缺失的数据(如果您小心的话)会使查询更简单并运行得更快。 我还将在表中添加一个标志以指示数据缺少填充的数据,以便如果 您需要稍后删除它(或创建一个没有它的视图)。

    我已经填写了缺失的数据,也填写了虚拟数据,这样就不需要外连接,从而多次提高查询性能。它不是“干净”和“完美”,但我遵循 Leflar 的第一定律,“总是选择可行的方法。”

    您可以在 Oracle 中创建一个作业,该作业将在非高峰时间自动运行以填充缺失的数据。看一看:This question on stackoverflow about creating jobs.

    【讨论】:

      【解决方案3】:

      您提出此请求的具体用例是什么?

      在我工作过的每个系统中,如果应该有 MARCH 的记录而没有 MARCH 的记录,那么用户想知道这个事实。除了任何他们可能想要调查 MARCH 记录丢失的原因之外。

      现在,如果这基本上是一个性能问题,那么您应该调整查询。或者,如果它出现问题——你想生成一个十二行的矩阵,如果由于某种原因没有记录,这很困难——那么这是另一回事,有多种可能的解决方案。

      但说真的,我认为数据库发明替换缺失记录的做法是一种不好的做法。

      编辑

      我从您最近对您的问题的评论中看到,这确实是一个性能问题 - 索引解决了这个问题。所以我觉得自己是对的。

      【讨论】:

      • 我同意 - 除非您确定这是正确的做法,否则填写缺失的数据,可能不应该这样做。
      • 此数据是由另一个应用程序生成的,实际上不适合此用途。存在“缺失”记录是非常合理的,只是这种新用途存在问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-03-15
      • 1970-01-01
      • 2012-11-19
      • 1970-01-01
      • 2018-09-14
      • 2019-01-07
      • 1970-01-01
      相关资源
      最近更新 更多