What is the best way to populate a load file for a date lookup dimension table?

梦想的初衷 提交于 2019-12-13 01:24:02

问题


Informix 11.70.TC4:

I have an SQL dimension table which is used for looking up a date (pk_date) and returning another date (plus1, plus2 or plus3_months) to the client, depending on whether the user selects a "1","2" or a "3".

The table schema is as follows:

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

UNIQUE INDEX on date_lookup(pk_date);

I have a load file (pipe delimited) containing dates from 01-28-2012 to 03-31-2014.

The following is an example of the load file:

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|

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

EDIT : Sir Jonathan's SQL statement using DATE(pk_date + n UNITS MONTH on 11.70.TC5 worked!

I generated a load file with pk_date's from 01-28-2012 to 12-31-2020, and plus1, plus2 & plus3_months NULL. Loaded this into date_lookup table, then executed the update statement below:

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);

Apparently, DATE() was able to convert pk_date to DATETIME, do the math with TC5's new algorithm, and return the result in DATE format!

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

The rules for this dimension table are:

  • If pk_date has 31 days in its month and plus1, plus2 or plus3_months only have 28, 29, or 30 days, then let plus1, plus2 or plus3 equal the last day of that month.
  • If pk_date has 30 days in its month and plus1, plus2 or plus3 has 28 or 29 days in its month, let them equal the last valid date of those month, and so on.
  • All other dates fall on the same day of the following month.

My question is: What is the best way to automatically generate pk_dates past 03-31-2014 following the above rules? Can I accomplish this with an SQL script, "sed", C program?

EDIT: I mentioned sed because I already have more than two years worth of data and could perhaps model the rest after this data, or perhaps a tool like awk is better?


回答1:


The best technique would be to upgrade to 11.70.TC5 (on 32-bit Windows; generally to 11.70.xC5 or later) and use an expression such as:

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

The DATETIME code was modified between 11.70.xC4 and 11.70.xC5 to generate dates according to the rules you outline when the dates are as described and you use the + n UNITS MONTH or equivalent notation.

This obviates the need for a table at all. Clearly, though, all your clients would also have to be on 11.70.xC5 too.

Maybe you can update your development machine to 11.70.xC5 and then use this property to generate the data for the table on your development machine, and distribute the data to your clients.

If upgrading at least someone to 11.70.xC5 is not an option, then consider the Perl script suggestion.




回答2:


Can it be done with SQL? Probably, but it would be excruciating. Ditto for C, and I think 'no' is the answer for sed.

However, a couple of dozen lines of perl seems to produce what you need:

#!/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);
}

Save that as futuredates.pl, chmod +x it and execute like this:

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

That seems to do the trick for me.



来源:https://stackoverflow.com/questions/11497714/what-is-the-best-way-to-populate-a-load-file-for-a-date-lookup-dimension-table

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!