Сравнение дат в Hive

Я работаю с Hive, и у меня есть таблица, структурированная следующим образом:

CREATE TABLE t1 (
  id INT,
  created TIMESTAMP,
  some_value BIGINT
);

мне нужно найти все строки t1 то чем 180 дней старых. Следующий запрос не дает строк, даже если в таблице присутствуют данные, соответствующие предикату поиска.

select * 
from t1 
where created > date_sub(from_unixtime(unix_timestamp()), 180);

каков подходящий способ выполнить сравнение дат в Hive?

5 ответов


как насчет:

where unix_timestamp() - created < 180 * 24 * 60 * 60

дата математика обычно проще, если вы можете просто сделать это с фактическими значениями метки времени.

или вы хотите, чтобы сократить только на целые дни? Тогда я думаю, что проблема в том, как вы конвертируете туда и обратно между ints и строками. Попробуйте:

where created > unix_timestamp(date_sub(from_unixtime(unix_timestamp(),'yyyy-MM-dd'),180),'yyyy-MM-dd')

прогулка по каждому UDF:

  1. unix_timestamp() возвращает int: текущее время в секундах с начала эпохи
  2. from_unixtime(,'yyyy-MM-dd') преобразуется в строку данный формат, например, '2012-12-28'
  3. date_sub(,180) вычитает 180 дней от этой строки, и возвращает новую строку в том же формате.
  4. unix_timestamp(,'yyyy-MM-dd') преобразует эту строку в int

если это все становится слишком волосатым, вы всегда можете написать UDF, чтобы сделать это самостоятельно.


в качестве альтернативы вы можете также использовать datediff. Тогда предложение будет
в случае Строковой метки времени (формат jdbc):

datediff(from_unixtime(unix_timestamp()), created) < 180;

в случае времени эпохи Unix:

datediff(from_unixtime(unix_timestamp()), from_unixtime(created)) < 180;

Я думаю, что, возможно, это ошибка улья, связанная с метка тип. Я пытался использовать его в последнее время и получив неверные результаты. Если я изменю вашу схему, чтобы использовать строку вместо timestamp, и значения в

гггг-ММ-ДД чч:мм:СС

формат, затем запрос select работал для меня.

согласно документации, улей должен иметь возможность конвертировать BIGINT, представляющий секунды эпохи в метка времени и что все существующие UDFs datetime работают с типом данных метки времени.

с этим простым запросом:

выберите from_unixtime (unix_timestamp ()), cast (unix_timestamp () как timestamp) от предела test_tt 1;

Я ожидал бы, что оба поля будут одинаковыми, но я получаю:

2012-12-29 00:47:43 1970-01-16 16:52:22.063

Я вижу и другие странности.


метка времени-миллисекунды
unix_timestamp в секундах
Вам нужно умножить RHS на 1000.

where created > 1000 * date_sub(from_unixtime(unix_timestamp()), 180);

после просмотра этого и ссылки на разница дат менее 15 минут в улье Я придумал решение. Хотя я не уверен, почему Hive не выполняет сравнение эффективно по датам как строкам (они должны сортировать и сравнивать лексикографически), работает следующее решение:

FROM (
    SELECT  id, value,
            unix_timestamp(created) c_ts, 
            unix_timestamp(date_sub(from_unixtime(unix_timestamp()), 180), 'yyyy-MM-dd') c180_ts
    FROM    t1
) x
JOIN t1 t ON x.id = t.id
SELECT  to_date(t.Created), 
        x.id, AVG(COALESCE(x.HighestPrice, 0)), AVG(COALESCE(x.LowestPrice, 0))
WHERE   unix_timestamp(t.Created) > x.c180_ts
GROUP BY to_date(t.Created), x.id ;