我希望能够从单个表中的多个记录中提取一个字段。例如,假设我有一个如下的模式
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似乎是一种很好的前进方式,但它要么不在这里工作,要么我缺乏创造力来使它工作。有人有什么建议吗?
谢谢, 布拉德
答案 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