如何在雅典娜(Presto)中查询和遍历结构数组?

时间:2019-03-15 04:22:17

标签: sql json amazon-athena presto

我有一个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" }
      ],

我不确定该怎么做。

  1. 如何查询结构数组以查找incomeTypes的重复"SALARY"

  2. 我是否必须遍历数组?

  3. 结果应该是什么样?

2 个答案:

答案 0 :(得分:3)

您可以将filtercardinality结合使用以过滤具有多个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来仅获取incomeTypeSALARY的那些,然后CARDINALITY来提取其长度结果。


对于SQL引擎,区分大小写绝非易事。总的来说,我认为您不应该期望他们尊重案件,而许多人则不会。尤其是雅典娜explicitly converts column names to lower case