我想在AWS Athena中创建一个存储在S3中的多个CSV文件的表格。
CSV具有带列名称的标题行。 我的问题是每个CSV中的列的顺序不同,我希望按名称获取列。
当我在Athena中尝试普通的CREATE TABLE时,我得到前两列。
CREATE EXTERNAL TABLE `test`(
`id` string,
`name` string)
ROW FORMAT SERDE
'org.apache.hadoop.hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES (
'escapeChar'='\\',
'quoteChar'='\"',
'separatorChar'=',')
STORED AS INPUTFORMAT
'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
's3://...'
TBLPROPERTIES (
'has_encrypted_data'='false')
这是一个例子:
csv 1:
+----+-------+-------+---------+
| id | name | price | comment |
+----+-------+-------+---------+
| 1 | shirt | 123 | abc |
| 2 | shoes | 222 | ddd |
+----+-------+-------+---------+
csv 2:
+----+------+-------+-------+---------+
| id | size | price | color | name |
+----+------+-------+-------+---------+
| 5 | L | 100 | red | shirt |
| 6 | S | 55 | white | t-shirt |
+----+------+-------+-------+---------+
我想要的表格:
+----+---------+
| id | name |
+----+---------+
| 1 | shirt |
| 2 | shoes |
| 5 | shirt |
| 6 | t-shirt |
+----+---------+
我得到的表格:
+----+-------+
| id | name |
+----+-------+
| 1 | shirt |
| 2 | shoes |
| 5 | L |
| 6 | S |
+----+-------+
由于
答案 0 :(得分:1)
对于不同的CSV,我会使用两个不同的表(您需要将CSV存储在不同的文件夹中)。
最后,为了获得id,两个CSV的名称结构我都会使用VIEW来合并来自不同表的必要列。
答案 1 :(得分:1)
IMO,Glue Crawler没有设置以选择列名并使用它们来定义表的架构,这有点遗憾。我们遇到了这个问题(S3中同一文件夹中的模式更改),这是我们解决的方法。
注意-如果您可以将架构(标题顺序)映射到特定的S3路径,则以下解决方案有效。
我们有四个文件。 a.csv
和b.csv
共享相同的架构,而c.csv
和d.csv
具有不同的架构。
$ cat a.csv
a,b
1,2
3,4
$ cat b.csv
a,b
5,6
3,4
$ cat c.csv
a,b,c
1,2,3
4,5,6
$ cat d.csv
a,c,d,x
6,7,8,9
1,2,3,4
这些保存在S3中:
$ aws s3 ls s3://example-s3-bucket/
2019-01-04 09:47:42 12 a.csv
2019-01-04 09:49:49 12 b.csv
2019-01-04 09:49:53 18 c.csv
2019-01-04 09:49:56 24 d.csv
为每个架构创建一个表,只需在其中传递相同的S3位置即可。
请注意,为简便起见,我省略了定界符和字段分隔符的定义。
create external table athena_testing_ab (
a int,
b int
)
LOCATION 's3://example-s3-bucket/'
;
create external table athena_testing_c (
a int,
b int,
c int
)
LOCATION 's3://example-s3-bucket/'
;
create external table athena_testing_d (
a int,
c int,
d int,
x int
)
LOCATION 's3://example-s3-bucket/'
;
UNION
s查询所有表我们现在查询这3个表,并将它们全部UNION
一起查询,并为每个表筛选适当的S3路径。
您可能想使用正则表达式或子字符串解析来更优雅地对$PATH
进行过滤,尤其是在存储桶中有成百上千个文件的情况下。
select
a,
b,
null as c,
null as d,
null as x
from
athena_testing_ab
where "$PATH" in ('s3://example-s3-bucket/a.csv', 's3://example-s3-bucket/b.csv')
union all
select
a,
b,
c,
null as d,
null as x
from
athena_testing_c
where "$PATH" in ('s3://example-s3-bucket/c.csv')
union all
select
a,
null as b,
c,
d,
x
from
athena_testing_d
where "$PATH" in ('s3://example-s3-bucket/d.csv')
答案 2 :(得分:0)
将文件放在不同的文件夹中,并使用Glue Crawler创建数据存储区。
答案 3 :(得分:0)
使用胶水爬虫。这将有所帮助。