Первая Строка Пропуска Внешней Таблицы Hive

Я использую версию Hive Cloudera и пытаюсь создать внешнюю таблицу над файлом csv, который содержит имена столбцов в первом столбце. Вот код, который я использую для этого.

CREATE EXTERNAL TABLE Test ( 
  RecordId int, 
  FirstName string, 
  LastName string 
) 
ROW FORMAT serde 'com.bizo.hive.serde.csv.CSVSerde' 
WITH SerDeProperties (  
  "separatorChar" = ","
) 
STORED AS TEXTFILE 
LOCATION '/user/File.csv'

Пример Данных

RecordId,FirstName,LastName
1,"John","Doe"
2,"Jane","Doe"

может кто-нибудь помочь мне с тем, чтобы пропустить первую строку или мне нужно добавить промежуточный шаг?

7 ответов


строки заголовка в данных являются постоянной головной болью в улье. За исключением изменения источника улья, я считаю, что вы не можете уйти без промежуточного шага. (Edit: это больше не верно, см. обновление ниже)

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

вы можете уйти без дополнительного шага в загрузке данных, если вы хотите отфильтровать строку заголовка для каждого запроса, который касается таблицы. К сожалению, это добавляет дополнительный набор почти везде. И вам придется стать умным / грязным, когда строка заголовка нарушает вашу схему. Если вы идете с этим подходом, вы можете подумать о написании пользовательского SerDe, который упрощает фильтрацию этой строки. К сожалению, SerDe не могут удалить строку полностью (или это может сформировать возможное решение), они должны вернуть что-то вроде null. Я никогда не видел этого подхода на практике, чтобы иметь дело с строками заголовков, так как это делает чтение болью, а чтение встречается гораздо чаще, чем письмо. Он может иметь место, если вы имеете дело с одной из таблиц или если строка заголовка является только одной строкой среди многих искаженных строк.

вы можете сделать эту фильтрацию один раз с изменениями при удалении этой первой строки в загрузке данных. А WHERE п. в INSERT заявление сделает это. Вы можете использовать утилиты, такие как sed, чтобы избавиться от него. Я видел оба подхода. Есть компромиссы между тем, какой подход вы принимаете, и ни один из них единственный истинный способ справиться со строками заголовка. К сожалению, оба эти подхода требуют времени и временного дублирования данных. Если вам абсолютно нужна строка заголовка для другого приложения, дублирование будет постоянным.

обновление:

из улья v0.13.0, вы можете использовать skip.заголовок.линия.рассчитывать. Вы также можете указать то же самое при создании таблицы. Например:

create external table testtable (name string, message string)
row format delimited 
fields terminated by '\t' 
lines terminated by '\n' 
location '/testtable'
tblproperties ("skip.header.line.count"="1");

пока у вас есть ответ от Даниэля, вот некоторые настройки, возможные с помощью OpenCSVSerde:

CREATE EXTERNAL TABLE `mydb`.`mytable`(
    `product_name` string,
    `brand_id` string,
    `brand` string,
    `color` string,
    `description` string,
    `sale_price` string)
PARTITIONED BY (
    `seller_id` string)
ROW FORMAT SERDE
    'org.apache.hadoop.hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES (
    'separatorChar' = '\t',
    'quoteChar' = '"',
    'escapeChar' = '\')
STORED AS INPUTFORMAT
    'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
    'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
    'hdfs://namenode.com:port/data/mydb/mytable'
TBLPROPERTIES (
    'serialization.null.format' = '',
    'skip.header.line.count' = '1')

при этом у вас есть полный контроль над разделителем, символом цитаты, escape-символом, обработкой null и обработкой заголовка.

посмотреть здесь и здесь.


просто добавьте ниже свойство в свой запрос, и первый заголовок или строка int запись не будет загружаться или она будет пропущена.

попробуй такое

tblproperties ("skip.header.line.count"="1");

Я не совсем уверен, работает ли он с форматом строк serde 'com.Бизо.улей.Серд.csv.CSVSerde 'но я думаю, что он должен быть похож на поля с разделителями формата строк, заканчивающиеся на','.
в вашем случае первая строка будет рассматриваться как обычная строка. Но первое поле не может быть INT, поэтому все поля для первой строки будут установлены как NULL. Вам нужно только один промежуточный шаг, чтобы исправить это:

INSERT OVERWRITE TABLE Test
SELECT * from Test WHERE RecordId IS NOT NULL

только один недостаток заключается в том, что исходный csv-файл будет изменен. Надеюсь, это поможет. ГЛ!


Я также боролся с этим и не нашел способа сказать улью пропустить первую строку, как, например, в Greenplum. В конце концов мне пришлось удалить его из файлов. например, " cat File.csv / grep-v RecordId > File_no_header.csv"


create external table table_name( 
Year int, 
Month int,
column_name data_type ) 
row format delimited fields terminated by ',' 
location '/user/user_name/example_data' TBLPROPERTIES('serialization.null.format'='', 'skip.header.line.count'='1');

пропустить.заголовок.линия.count работает, но если у вас есть какой-то внешний инструмент доступа к этой таблице , он все равно увидит, что фактические данные без пропуска этих строк