날짜를 조회하고 다른 날짜를 반환하는 SQL 팩트 테이블이 있습니다.
테이블 구조는 다음과 같습니다.
TABLE date_lookup
(
pk_date DATE,
plus1_months DATE,
plus2_months DATE,
plus3_months DATE
);
UNIQUE INDEX on date_lookup(pk_date);
2012년 1월 28일부터 2014년 3월 31일까지의 날짜를 포함하는 로드된 파일(파이프로 구분됨)이 있습니다.
다음은 파일을 로드하는 예입니다.
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|
이 팩트 테이블의 규칙은 다음과 같습니다.
IF pk_date has more than 28 days in its month
AND plus1, plus2 or plus3_months only has 28, 29 or 30 days
THEN let plus1, plus2 or plus3 equal the last day of the following month.
sed
내 질문은 다음과 같습니다. 위의 규칙에 따라 로드 파일에 대해 2014년 3월 31일 이후에 더 많은 날짜를 생성 할 수 있습니까 ? 아니면 이를 수행하는 프로그램을 작성해야 합니까?
답변1
이 경우 이것이 sed
작업에 적합한 도구인지 의심됩니다. awk
이미 익숙하다면 사용하고, awk
그렇지 않으면 프로그램을 작성하는 것이 좋을 것 같습니다 .
sed
나는 당신이 언급한 것보다 더 엄격한 요구 사항으로 MSC/NASTRAN 입력 파일을 사용 하고 생성하는 엔지니어를 알고 있지만 awk
그는 이러한 도구에 매우 익숙하므로 도구에서 나오는 비밀스럽고 정보가 없는 오류 메시지가 awk
그를 괴롭히지 않습니다.
를 사용하여 이 작업을 수행하려면 awk
입력을 전처리하여 "-" 및 "|" 문자를 제거하는 것이 좋습니다. 프로그램을 awk
별도의 파일에 작성합니다. 텍스트 필드 위치($1, $2, $3...)를 사용하고 출력에 대한 SQL INSERT 문을 작성합니다. 여러 번 시도해야 하므로 최대한 자동화하세요.
답변2
sed에서 날짜 연산을 수행하는 것은 기술적으로 가능하지만 작업에 적합한 도구는 아닙니다. awk 또는 Perl과 같은 정수 연산 기능이 내장된 도구를 사용하세요.
귀하의 요구 사항은 날짜 연산에 대해 특이하므로 날짜 산술을 하드코딩하지 않으려면 풍부한 날짜 조작 라이브러리가 필요합니다. 진주의Date::Manip
유사한 기능을 가지고 있습니다 Date_DaysInMonth
.
#!/usr/bin/env perl
use strict;
use warnings;
use Date::Manip;
use List::Util qw(/./);
sub shift_month {
my ($delta, $y, $m, $d) = @_;
$m += $delta;
$y += $m / 12;
$m %= 12;
return ($y, $m, min($d, Date_DaysInMonth($m, $y)));
}
my $next_day = ParseDateDelta("1 day");
my ($cur, $end) = (ParseDate($ARGV[0]), ParseDate($ARGV[1]));
while (Date_Cmp($cur, $end) < 0) {
my @ymd = UnixDate($cur, qw(%Y %m %d));
foreach my $i (0..3) {
printf "%02d-%04d-%02d|", @{[shift_month($i, @ymd)]}[1, 0, 2];
}
$cur = DateCalc($cur, $next_day);
print "\n";
}