为日期查找维度表填充加载文件的最佳方法是什么?

时间:2012-07-16 03:14:46

标签: c++ sql date sed informix

Informix 11.70.TC4:

我有一个SQL维度表,用于查找日期(pk_date)并将另一个日期(plus1,plus2或plus3_months)返回给客户端,具体取决于用户是选择“1”,“2”还是一个“3”。

表模式如下:

TABLE date_lookup
(
    pk_date DATE,
    plus1_months DATE,
    plus2_months DATE,
    plus3_months DATE
);

UNIQUE INDEX on date_lookup(pk_date);

我有一个加载文件(管道分隔),其中包含从01-28-2012到03-31-2014的日期。

以下是加载文件的示例:

01-28-2012|02-28-2012|03-28-2012|04-28-2012|
01-29-2012|02-29-2012|03-29-2012|04-29-2012|
01-30-2012|02-29-2012|03-30-2012|04-30-2012|
01-31-2012|02-29-2012|03-31-2012|04-30-2012|
...
03-31-2014|04-30-2014|05-31-2014|06-30-2014|

............................................... .........................................

编辑: Jonathan爵士在11.70.TC5上使用DATE(pk_date + n UNITS MONTH的SQL语句有效!

enter image description here

我在01-28-2012到12-31-2020之间生成了一个pk_date的加载文件,加上1,加上2& plus3_months NULL。将此加载到date_lookup表中,然后执行以下更新语句:

UPDATE date_lookup
   SET plus1_months = DATE(pk_date + 1 UNITS MONTH),
       plus2_months = DATE(pk_date + 2 UNITS MONTH),
       plus3_months = DATE(pk_date + 3 UNITS MONTH);

显然,DATE()能够将pk_date转换为DATETIME,使用TC5的新算法进行数学运算,并以DATE格式返回结果!

............................................... ..........................................

此维度表的规则是:

  • 如果pk_date在其当月有31天且plus1,plus2或plus3_months只有28天,29天或30天,那么让plus1,plus2或plus3等于该月的最后一天。
  • 如果pk_date在其月份中有30天且plus1,plus2或plus3在其月份中有28天或29天,则让它们等于该月份的最后有效日期,依此类推。
  • 所有其他日期都是在下个月的同一天。

我的问题是:按照上述规则,在2014年3月31日之后自动生成pk_dates的最佳方法是什么?我可以用SQL脚本“sed”,C程序来完成这个吗?

编辑:我提到sed,因为我已经拥有超过两年的数据和     或许可以在这些数据之后对剩下的数据进行建模,或者像awk之类的工具可能更好?

2 个答案:

答案 0 :(得分:1)

可以用SQL完成吗?可能,但这会令人难以忍受。同样的C,我认为'不'是sed的答案。

但是,几十行perl似乎可以产生你需要的东西:

#!/usr/bin/perl

use strict;
use warnings;
use DateTime;

my @dates;

# parse arguments
while (my $datep = shift){
    my ($m,$d,$y) = split('-', $datep);
    push(@dates, DateTime->new(year => $y, month => $m, day => $d))
        || die "Cannot parse date $!\n";
}

open(STDOUT, ">", "output.unl") || die "Unable to create output file.";
my ($date, $end) = @dates;
while( $date < $end ){
    my @row = ($date->mdy('-')); # start with pk_date
    for my $mth ( qw[ 1 2 3 ] ){
        my $fut_d = $date->clone->add(months => $mth);
        until   (
                    ($fut_d->month == $date->month + $mth
                       && $fut_d->year == $date->year) ||
                    ($fut_d->month == $date->month + $mth - 12
                       && $fut_d->year > $date->year)
                ){
                    $fut_d->subtract(days => 1); # step back until criteria met
                }
        push(@row, $fut_d->mdy('-'));
    }
    print STDOUT join("|", @row, "\n");
    $date->add(days => 1);
}

将其保存为futuredates.pl,chmod +x并执行如下:

$ futuredates.pl 04-01-2014 12-31-2020

这似乎对我有用。

答案 1 :(得分:1)

最好的技术是升级到11.70.TC5(在32位Windows上;通常为11.70.xC5或更高版本)并使用如下表达式:

SELECT DATE(given_date + n UNITS MONTH)
  FROM Wherever
...

DATETIME代码在11.70.xC4和11.70.xC5之间进行了修改,以根据您在描述日期时所概述的规则生成日期,并使用+ n UNITS MONTH或等效符号。

这完全不需要桌子。显然,你的所有客户也必须在11.70.xC5上。

也许您可以将开发计算机更新到11.70.xC5,然后使用此属性为开发计算机上的表生成数据,并将数据分发给您的客户端。

如果不能将至少某人升级到11.70.xC5,请考虑Perl脚本建议。