我有一个S3存储桶,具有500,000条以上的json
记录,例如
{
"userId": "00000000001",
"profile": {
"created": 1539469486,
"userId": "00000000001",
"primaryApplicant": {
"totalSavings": 65000,
"incomes": [
{ "amount": 5000, "incomeType": "SALARY", "frequency": "FORTNIGHTLY" },
{ "amount": 2000, "incomeType": "OTHER", "frequency": "MONTHLY" }
]
}
}
}
我在雅典娜创建了一个新桌子
CREATE EXTERNAL TABLE profiles (
userId string,
profile struct<
created:int,
userId:string,
primaryApplicant:struct<
totalSavings:int,
incomes:array<struct<amount:int,incomeType:string,frequency:string>>,
>
>
)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
WITH SERDEPROPERTIES ( 'ignore.malformed.json' = 'true')
LOCATION 's3://profile-data'
我对incomeTypes
感兴趣,例如"SALARY"
,"PENSIONS"
,"OTHER"
等。并且每次更改jsonData.incometype
都运行此查询:
SELECT jsonData
FROM "sampledb"."profiles"
CROSS JOIN UNNEST(sampledb.profiles.profile.primaryApplicant.incomes) AS la(jsonData)
WHERE jsonData.incometype='SALARY'
这与CROSS JOIN UNNEST
一起使用效果很好,它使收入数组变平,因此上面的数据示例将跨越两行。唯一的特质是CROSS JOIN UNNEST
使所有字段名都变为小写,例如。一排看起来像这样:
{amount=1520, incometype=SALARY, frequency=FORTNIGHTLY}
现在我被问到有多少用户有两个或更多"SALARY"
条目,例如
"incomes": [
{ "amount": 3000, "incomeType": "SALARY", "frequency": "FORTNIGHTLY" },
{ "amount": 4000, "incomeType": "SALARY", "frequency": "MONTHLY" }
],
我不确定该怎么做。
如何查询结构数组以查找incomeTypes
的重复"SALARY"
?
我是否必须遍历数组?
结果应该是什么样?
答案 0 :(得分:3)
您可以将filter
与cardinality
结合使用以过滤具有多个incomeType = 'SALARY'
的数组元素。
这可以进一步改善,以免使用reduce
来实现中间数组(请参阅文档中的示例;由于它们不能直接回答您的问题,因此我在这里不引用它们)。
答案 1 :(得分:1)
UNNEST
是一项非常强大的功能,可以使用它来解决此问题。但是,我认为使用Presto's Lambda functions更直接:
SELECT COUNT(*)
FROM sampledb.profiles
WHERE CARDINALITY(FILTER(profile.primaryApplicant.incomes, income -> income.incomeType = 'SALARY')) > 1
此解决方案使用profile.primaryApplicant.incomes
数组上的FILTER
来仅获取incomeType
为SALARY
的那些,然后CARDINALITY
来提取其长度结果。
对于SQL引擎,区分大小写绝非易事。总的来说,我认为您不应该期望他们尊重案件,而许多人则不会。尤其是雅典娜explicitly converts column names to lower case。