AnalysisException: default.date_format() unknown for database default. Currently this database has 0 functions.
Impala 에는 date_format() 함수가 없다. 함수 이름을 모르면 Impala 는 현재 데이터베이스의 UDF 로 간주하고 위 메시지를 낸다. default. 접두사가 붙는 이유가 그것이며, 오타가 아니라 존재하지 않는 함수라는 뜻이다.
Hive 쿼리를 그대로 옮길 때 가장 먼저 걸리는 부분이다. 대응 함수는 from_timestamp() 와 from_unixtime() 이다.
SELECT from_timestamp(now(), 'yyyy-MM-dd');
SELECT from_timestamp(now(), 'yyyyMMdd');
SELECT from_unixtime(unix_timestamp(), 'yyyy-MM-dd HH:mm:ss');
포맷 문자열은 Java SimpleDateFormat 계열이다. yyyy · MM · dd · HH · mm · ss · SSS 를 쓰며 대소문자를 구분한다. MySQL 식 %Y%m%d 는 통하지 않는다.
now() 와 current_timestamp() 는 같은 값을 준다. 괄호를 빼면 컬럼 이름으로 해석돼 Could not resolve column/field reference 가 나므로 괄호를 붙인다.
SELECT now(), current_timestamp();
SELECT from_timestamp(now(), 'yyyyMMdd') AS ymd;
Oracle 의 SYSDATE 에 해당하는 것이 now() 다.
문자열 20241119 형태의 날짜를 29일 빼서 다시 같은 형태로 만드는 Hive 쿼리는 이렇게 바꾼다.
-- Hive
SELECT date_format(date_sub(CAST(CONCAT(SUBSTR(dt,1,4),'-',SUBSTR(dt,5,2),'-',SUBSTR(dt,7,2)) AS DATE), 29), 'yyyyMMdd');
-- Impala
SELECT from_timestamp(days_sub(to_timestamp(dt, 'yyyyMMdd'), 29), 'yyyyMMdd');
to_timestamp(문자열, 포맷) 으로 파싱하고, days_sub() · date_sub() 로 계산한 뒤 from_timestamp() 로 다시 포맷한다.
시작·종료 시각의 차이를 초 단위로 구할 때는 unix_timestamp() 의 차를 쓴다.
SELECT unix_timestamp(end_ts) - unix_timestamp(start_ts) AS dur_sec FROM t;
unix_timestamp() 는 초 단위로 잘라내므로 밀리초가 사라진다. TIMESTAMP 타입 자체는 초 미만 정밀도를 갖고 있으므로, 밀리초까지 필요하면 따로 더한다.
SELECT (unix_timestamp(end_ts) * 1000 + millisecond(end_ts))
- (unix_timestamp(start_ts) * 1000 + millisecond(start_ts)) AS dur_ms
FROM t;
날짜 차이는 datediff(end, start) 가 일 단위로 돌려준다.
| 목적 | 함수 |
|---|---|
| 문자열 → TIMESTAMP | to_timestamp(str, pattern) |
| TIMESTAMP → 문자열 | from_timestamp(ts, pattern) |
| epoch → 문자열 | from_unixtime(bigint, pattern) |
| 월·일 단위 절삭 | trunc(ts, 'MONTH'), trunc(ts, 'DD') |
| 구성요소 추출 | extract(ts, 'year'), year(ts), month(ts), millisecond(ts) |
| 가감 | days_add · days_sub · months_add · date_add · date_sub |
| UTC 변환 | from_utc_timestamp(ts, 'Asia/Seoul'), to_utc_timestamp(ts, 'Asia/Seoul') |