как разделить столбцы в улье

У меня есть файл:

id,name,address
001,adam,1-A102,mont vert
002,michael,57-D,costa rica

Мне нужно создать таблицу кустов, которая будет содержать три столбца: id, name и address, используя запятую, но здесь сам столбец адреса содержит запятую между ними. Как мы собираемся справиться с этим.


person Sanskar Suman    schedule 16.08.2019    source источник


Ответы (1)


Одним из возможных решений является использование RegexSerDe:

CREATE TABLE table my_table (
    id       string,
    name     string,
    address  string
) 
ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.RegexSerDe'
WITH SERDEPROPERTIES ('input.regex'='^(.*?),(.*?),(.*?)$') 
location 'put location here' 
;

Замените свойство местоположения на местоположение вашей таблицы и поместите файлы в это место.

Первая группа (.*?) будет соответствовать всему до первой запятой, вторая группа будет соответствовать всему после первой запятой и до второй запятой, а третья группа будет соответствовать всему после второй запятой.

Также добавьте TBLPROPERTIES("skip.header.line.count"="1"), если вам нужно пропустить заголовок, и он всегда существует в файле. Если заголовок может отсутствовать, вы можете отфильтровать строки заголовка, используя where id !='id'

Также вы можете легко протестировать Regex для извлечения столбцов даже без создания таблицы, например:

select regexp_replace('002,michael,57-D,costa rica','^(.*?),(.*?),(.*?)$','$1|$2|$3');

Результат:

002|michael|57-D,costa rica

В этом примере запрос возвращает три группы, разделенные |. Таким образом, вы можете легко протестировать свое регулярное выражение, проверить, правильно ли определены группы, прежде чем создавать с ним таблицу.

Ответ на вопрос в комментарии. Вы можете иметь адрес с запятой и еще один столбец без запятой, например:

select regexp_replace('001,adam,1-A102, mont vert,sydney','^(.*?),(.*?),(.*?),([^,]*?)$','$1|$2|$3|$4');

Возвращает:

001|adam|1-A102, mont vert|sydney

Проверка запятой не является обязательной в столбце «Адрес»:

hive> select regexp_replace('001,adam,1-A102 mont vert,sydney','^(.*?),(.*?),(.*?),([^,]*?)$','$1|$2|$3|$4');

Возвращает:

001|adam|1-A102 mont vert|sydney

Прочтите эту статью для лучшего понимания: https://community.cloudera.com/t5/Community-Articles/Using-Regular-Expressions-to-Extract-Fields-for-Hive-Tables/ta-p/247562

[^,] означает не запятую, последний столбец может быть любым, кроме запятой.

И, конечно же, добавьте еще один столбец в DDL.

person leftjoin    schedule 16.08.2019
comment
id,name,address,city 001,adam,1-A102,mont vert,sydney 002,michael,57-D,costa rica,melbourne Предположим, я добавил сюда еще один столбец, Итак, как мы собираемся реализовать здесь serde. - person Sanskar Suman; 04.09.2019
comment
@SanskarSuman И как вы можете определить правило, чтобы определить, это адрес, содержащий запятую, или адрес, (запятая) город? Я спрашиваю об этом, потому что вы сказали, что адрес может содержать запятую. Если вы можете определить правило, тогда можно будет реализовать регулярное выражение. - person leftjoin; 04.09.2019
comment
Это то, что я спрашиваю здесь. Если у меня есть дополнительный столбец city в конце, то как я могу убедиться, что эти данные будут загружены в мой последний столбец в таблице куста, например: - output - 002|michael|57-D,costa rica | Sydney input- 002,michael,57-D,costa rica,Sydney позволяет считать, что столбец адреса не содержит названия города, и для этого у нас есть отдельный столбец города - person Sanskar Suman; 04.09.2019