可扩展的解决方案,以获取BigQuery中每个ID的最新行

时间:2016-08-28 05:43:18

标签: sql google-bigquery

我有一个非常大的表格,其中包含字段ID,另一个字段为collection_time。我想为每个ID选择最新记录。不幸的是(ID, collection_time)时间的组合在我的数据中并不是唯一的。我只想要一个最大collection time的记录。我尝试了两种解决方案,但它们都没有对我有用:

首先:使用查询

SELECT *  FROM 
(SELECT *, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY collection_time) as rn 
FROM mytable)  where rn=1

这导致Resources exceeded错误,我猜是因为查询中的ORDER BY

第二 使用表和最新时间​​之间的连接:

(SELECT tab1.* 
FROM mytable AS tab1
INNER JOIN EACH 
(SELECT ID, MAX(collection_time) AS second_time 
FROM mytable GROUP EACH BY ID) AS tab2
ON tab1.ID=tab2.ID AND tab1.collection_time=tab2.second_time) 

此解决方案对我不起作用,因为(ID, collection_time)不是唯一的,因此在JOIN结果中,每个ID会有多行。

我想知道是否有针对resourcesExceeded错误的解决方法,或者在我的情况下可以使用的其他查询?

6 个答案:

答案 0 :(得分:3)

快速和脏选项 - 将您的两个查询合并为一个 - 首先使用最新的collection_time获取所有记录(使用您的第二个查询),然后使用您的第一个查询对其进行重复删除:

SELECT * FROM (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY tab1.ID) AS rn 
  FROM (
    SELECT tab1.* 
    FROM mytable AS tab1
    INNER JOIN (
      SELECT ID, MAX(collection_time) AS second_time 
      FROM mytable GROUP BY ID
    ) AS tab2
    ON tab1.ID=tab2.ID AND tab1.collection_time=tab2.second_time
  )
)
WHERE rn = 1  

使用标准SQL(由S.Mohsen sh提出)

WITH myTable AS (
  SELECT 1 AS ID, 1 AS collection_time
),
tab1 AS (
  SELECT ID,
  MAX(collection_time) AS second_time 
  FROM myTable GROUP BY ID
),
tab2 AS (
  SELECT * FROM myTable
),
joint AS (
  SELECT tab2.* 
  FROM tab2 INNER JOIN tab1
  ON tab2.ID=tab1.ID AND tab2.collection_time=tab1.second_time 
)
SELECT * EXCEPT(rn) 
FROM (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY ID) AS rn 
  FROM joint
)
WHERE rn=1

答案 1 :(得分:1)

如果您不在乎为每一列编写一段代码:

SELECT ID, 
  ARRAY_AGG(col1 ORDER BY collection_time DESC)[OFFSET(0)] AS col1,
  ARRAY_AGG(col2 ORDER BY collection_time DESC)[OFFSET(0)] AS col2
FROM myTable
GROUP BY ID

答案 2 :(得分:0)

根据您的评论,考虑到您有一张包含唯一ID's的表格,您需要找到最新的collection_time。以下是使用Correlated Sub-Query执行此操作的另一种方法。试一试。

SELECT id, 
       (SELECT Max(collection_time) 
        FROM   mytable B 
        WHERE  A.id = B.id) AS Max_collection_time 
FROM   id_table A 

答案 3 :(得分:0)

另一种解决方案,它可以更具可扩展性,因为它避免了对同一个表的多次扫描(在上面的答案中会发生自连接和相关子查询)。此解决方案仅适用于标准SQL(取消选中“使用旧版SQL”选项):

SELECT 
  ID, 
  (SELECT srow.* 
   FROM UNNEST(t.srows) srow 
   WHERE srow.collection_time = MAX(srow.collection_time))
FROM
  (SELECT ID, ARRAY_AGG(STRUCT(col1, col2, col3, ...)) srows 
   FROM id_table 
   GROUP BY ID) t

答案 4 :(得分:0)

item = html.find_all("div", class_ = classid)

这将为您完成工作,并且考虑到架构不断变化的事实,因此可以伸缩,您不必更改此

答案 5 :(得分:0)

简短且可扩展的版本:

select array_agg(t order by collection_time desc limit 1)[offset(0)].*
from mytable t
group by t.id;