1

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|

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

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

在此处输入图像描述

我生成了一个 pk_date 从 01-28-2012 到 12-31-2020 的加载文件,并且 plus1、plus2 和 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 天,则让它们等于该月的最后一个有效日期,依此类推。
  • 所有其他日期都在下个月的同一天。

我的问题是:按照上述规则自动生成 pk_dates 过去 03-31-2014 的最佳方法是什么?我可以使用 SQL 脚本、“sed”、C 程序来完成这项工作吗?

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

4

2 回答 2

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

这似乎对我有用。

于 2012-07-16T04:23:48.327 回答
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 脚本建议。

于 2012-07-16T22:09:07.353 回答