![sed를 사용하여 날짜 조회 팩트 테이블에 대한 로드 파일을 생성할 수 있나요?](https://rvso.com/image/23958/sed%EB%A5%BC%20%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC%20%EB%82%A0%EC%A7%9C%20%EC%A1%B0%ED%9A%8C%20%ED%8C%A9%ED%8A%B8%20%ED%85%8C%EC%9D%B4%EB%B8%94%EC%97%90%20%EB%8C%80%ED%95%9C%20%EB%A1%9C%EB%93%9C%20%ED%8C%8C%EC%9D%BC%EC%9D%84%20%EC%83%9D%EC%84%B1%ED%95%A0%20%EC%88%98%20%EC%9E%88%EB%82%98%EC%9A%94%3F.png)
날짜를 조회하고 다른 날짜를 반환하는 데 사용되는 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.
내 질문은 다음과 같습니다. 내 로드 파일에 대해 위의 규칙에 따라 2014년 3월 31일 이후 더 많은 날짜를 생성하는 데 사용할 수 있습니까? sed
아니면 이를 수행하기 위한 프로그램을 작성해야 합니까?
답변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";
}