PARSE_DATE: неверный результат анализа функции BigQuery / Standard SQL - PullRequest
0 голосов
/ 05 февраля 2019

У меня есть следующий код в BigQuery (стандартный SQL):

SAFE_CAST (PARSE_DATE('%Y-%m-%d',JSON_EXTRACT_SCALAR(g.p_dataforanalytics,'$.birthday') ) as string)

Сбой из-за:

Неверный результат из-за функции синтаксического анализа

Проблема в том, что у меня нет контроля над данными, которые я получаю в g.p_dataforanalytics, некоторые из них - чистый мусор и не в правильном формате, иногда это даже не разумное значение.Есть ли способ определить, что если PARSE_DATE() не удастся, он вернет NULL и не выбросит запрос?

В основном я ищу что-то вроде try / catch на любом языке программирования?

Ответы [ 2 ]

0 голосов
/ 05 февраля 2019

Ниже для стандартного SQL BigQuery и (я думаю) покрывает большинство сумасшедших изменений представлений даты, используя moment.js библиотеку через BigQuery UDF с внешними библиотеками.

Примечание: вам нужно загрузить moment.js в your_bucket на GCS

#standardSQL
CREATE TEMPORARY FUNCTION PARSE_DATE_CUSTOM(format_string STRING, date_string STRING )
RETURNS STRING
LANGUAGE js AS """
        return moment(date_string).format(format_string);
"""
OPTIONS (
    library="gs://your_bucket/moment.js"
);
SELECT 
  JSON_EXTRACT_SCALAR(g.p_dataforanalytics, '$.birthday') birthday_in_json,
  PARSE_DATE_CUSTOM('YYYY-MM-DD', JSON_EXTRACT_SCALAR(g.p_dataforanalytics, '$.birthday')) birthday
FROM `project.dataset.table` g

Как вы можете видеть - здесь представлена ​​новая пользовательская функция PARSE_DATE_CUSTOM(format_string STRING, date_string STRING ), которая принимает любыестрока, представляющая дату и формат, в котором вы хотите получить конечный результат. Поддерживаемые форматы: здесь

Вы можете протестировать, поиграть с выше, используя фиктивные данные, как в упрощенном примере ниже

#standardSQL
CREATE TEMPORARY FUNCTION PARSE_DATE_CUSTOM(format_string STRING, date_string STRING )
RETURNS STRING
LANGUAGE js AS """
        return moment(date_string).format(format_string);
"""
OPTIONS (
    library="gs://your_bucket/moment.js"
);
WITH `project.dataset.table` AS (
  SELECT '{"birthday":"2000-12-31"}' p_dataforanalytics UNION ALL
  SELECT '{"birthday":"2000-15-31"}' UNION ALL
  SELECT '{"birthday":"12/31/2000"}' UNION ALL
  SELECT '{"birthday":"31 Dec 2000"}' UNION ALL
  SELECT '{"birthday":"Around 2000, Dec 31"}' 
)
SELECT 
  JSON_EXTRACT_SCALAR(g.p_dataforanalytics, '$.birthday') birthday_in_json,
  PARSE_DATE_CUSTOM('YYYY-MM-DD', JSON_EXTRACT_SCALAR(g.p_dataforanalytics, '$.birthday')) birthday
FROM `project.dataset.table` g

с результатом

Row     birthday_in_json        birthday     
1       2000-12-31              2000-12-31   
2       2000-15-31              Invalid date     
3       12/31/2000              2000-12-31   
4       31 Dec 2000             2000-12-31   
5       Around 2000, Dec 31     2000-12-31   
0 голосов
/ 05 февраля 2019

Используйте префикс SAFE. в синтаксическом разборе :

SAFE.PARSE_DATE('%Y-%m-%d', JSON_EXTRACT_SCALAR(g.p_dataforanalytics, '$.birthday') )

Я не вижу полезности преобразования этого обратно в строку, если только вы не хотели такого решения:

COALESCE(FORMAT('%Y-%m-%d',
                COALESCE(SAFE.PARSE_DATE('%Y-%m-%d', JSON_EXTRACT_SCALAR(g.p_dataforanalytics, '$.birthday'), 
                         SAFE.PARSE_DATE('%m/%d/%Y', JSON_EXTRACT_SCALAR(g.p_dataforanalytics, '$.birthday')
                        ) 

                ), JSON_EXTRACT_SCALAR(g.p_dataforanalytics, '$.birthday'
        )

То есть, если код тестировал разные форматы для даты, выбрал один, вернул его обратно в формат ГГГГ-ММ-ДД.И, если ни один из форматов не сработал, то сохранил исходное значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...