从大查询中的多个记录中提取并连接相同的字段

时间:2016-05-09 05:36:02

标签: google-bigquery

我希望能够从单个表中的多个记录中提取一个字段。例如,假设我有一个如下的模式

userId,eventTimestamp,theField

我想要做的是能够连接该领域的所有实例' theField'一起由eventTimestamp命令的给定userId的单个字符串。而对于额外的皱纹,我可以说我只想包括第一个最早的最古老的记录。

我的第一次尝试是尝试类似的事情:

 SELECT
 userId,
 eventTimestamp,
 LEAD(theField,0) OVER (PARTITION BY userId ORDER BY eventTimestamp) AS step0,
 LEAD(theField,1) OVER (PARTITION BY userId ORDER BY eventTimestamp) AS step1,
 ....,
 LEAD(theField,50) OVER (PARTITION BY userId ORDER BY eventTimestamp) AS step50,

然后下一步是将第一步包装在另一个SELECT语句中,如下所示:

 SELECT userId, eventTimestamp, CONCAT(STRING(step0), STRING(step1),...,STRING(step50)) as concatenatedString
 FROM [whateverDataset.whateverTable],
 GROUP BY
 userId, eventTimestamp

这种方法不起作用,因为如果我有超过50个步骤(我这样做),那么我最终会为每个外部SELECT语句获取多行,基本上是N-50行,其中N =特定userId的记录总数。一个解决方案'这将是在内部SELECT语句中有一个HAVING语句,以限制自己仅报告前50个记录,但总体而言,这似乎是一个相当麻烦的解决方案。在非BigQuery的SQL变体中,GROUP_CONCAT似乎是一种很好的前进方式,但它要么不在这里工作,要么我缺乏创造力来使它工作。有人有什么建议吗?

谢谢, 布拉德

1 个答案:

答案 0 :(得分:3)

  

对于BigQuery Legacy SQL:

SELECT
  userid, GROUP_CONCAT(theField) AS Fields
FROM (
  SELECT 
    userid, eventTimestamp, theField, 
    ROW_NUMBER() OVER(PARTITION BY userid ORDER BY eventTimestamp DESC) AS pos
  FROM YourTable
  ORDER BY eventTimestamp
)
WHERE pos < 51
GROUP BY userid 

请注意:内部ORDER BY不保证GROUP_CONCAT中字段的顺序。但是,到目前为止,在所有实际案例中,我都看到订单正在进行中。所以,仔细测试

  

对于BigQuery Standard SQL:
  请勿忘记取消选中显示选项

下的Use Legacy SQL复选框
SELECT 
  userid, 
  (SELECT STRING_AGG(fields) FROM t.fields) AS fields
FROM (
  SELECT 
    userid, 
    ARRAY(SELECT theField FROM t.fields ORDER BY eventTimestamp) fields 
  FROM (
    SELECT 
      userid, 
      ARRAY_AGG(STRUCT(theField, eventTimestamp)) fields
    FROM (
      SELECT
        userid,
        eventTimestamp,
        theField,
        ROW_NUMBER() OVER(PARTITION BY userid ORDER BY eventTimestamp DESC) AS pos
      FROM YourTable
    ) 
    WHERE pos < 51
    GROUP BY userid
  ) t
) t