2017-09-25 52 views
1

我有2個月拼花文件2017_01.parquet2017_08.parquet和那些模式是:使用SQL火花讀取與實木複合地板格式的非現有列

2017_01.parquet:

root 
|-- value: struct (nullable = true) 
| |-- version: struct (nullable = true) 
| | |-- major: integer (nullable = true) 
| | |-- minor: integer (nullable = true) 
| |-- guid: string (nullable = true) 

2017_08.parquet:

root 
|-- value: struct (nullable = true) 
| |-- version: struct (nullable = true) 
| | |-- major: integer (nullable = true) 
| | |-- minor: integer (nullable = true) 
| | |-- vnum: integer (nullable = true) 
| |-- guid: string (nullable = true) 

和我的代碼

SQL = """ 
SELECT value.version.major, 
     value.version.minor, 
     value.version.vnum 
FROM OUT_TABLE 
LIMIT 10""" 

parquetFile = spark.read.parquet("/mydata/2017_08.parquet") 
parquetFile.createOrReplaceTempView("OUT_TABLE") 
out_osce = spark.sql(SQL) 
out_osce.show() 

當我加載2017_08.parquet顯示:

+-----+-----+----+ 
|major|minor|vnum| 
+-----+-----+----+ 
| 0001| 4610|1315| 
| 0002| 4610|6206| 
| 0003| 4610|6125| 

,但如果我加載2017_01.parquet像 parquetFile = spark.read.parquet("/mydata/2017_01.parquet")

SQL顯示錯誤:

pyspark.sql.utils.AnalysisException: u'No such struct field vnum in major, minor; line 4 pos 11' 

我知道原因是2017_01.parquet沒有vnum專欄,我有兩個解決方案,一個是使用mergeSchema另一種是在閱讀鑲木地板文件時使用模式,但這些方式也有一個大問題。

第一種解決方案需要讀2017_08.parquet,如果我不需要08的數據將是一個問題,如果運氣不好vnum是一個選項列和08沒有此列仍然錯誤

第二種解決方案是在讀取模式時給出的,如spark.read.schema(schema).parquet("/mydata/2017_01.parquet"),這種方式需要先編寫模式,但如果文件是非常複雜的嵌套表,用戶可能無法編寫模式,模式將更新。

我要問人有第三種解決辦法,然後使只讀2017_01.parquet和輸出,如:

+-----+-----+----+ 
|major|minor|vnum| 
+-----+-----+----+ 
| 0001| 4600|null| 
| 0002| 4600|null| 
| 0003| 4600|null| 
+0

感謝編輯建議@himanshuIIITian –

回答

0

您可以簡單地使用case語句或合併讀取時:

parquetFile = spark.read.parquet("") \ 
       .withColumn("vnum", coalesce("vnum")) 

來自文檔:

coalesce(e:列*):列

返回非空的第一列,如果所有輸入均爲空,則返回null。

如果您的Parquet文件有這個字段,它將被使用。如果沒有,將會使用空值,並且新列將會出現在您的模式中

+0

當我使用coalesce(「vnum」)時,它總是顯示錯誤,所以我嘗試使用點亮(「 「),但問題是'.withColumn'新的列添加在頂層,如果我有嵌套模式,它不能將列添加到正確的級別 –

相關問題