bigquery:依靠子查询的联合

Posted

技术标签:

【中文标题】bigquery:依靠子查询的联合【英文标题】:bigquery: count on union of subqueries 【发布时间】:2015-05-27 17:25:19 【问题描述】:

我有两个表(lightenhanced),它们的架构略有不同。第二个表 (enhanced) 有额外的可为空字段 t。 我想根据两个字段(d,p)从每个组的第一个和第二个表中获取行数

为了实现这一点,我使用带星号的子查询联合

select
  d
  , p
  ,count(1) - count(t) light_cnt
  ,count(t) enhanced_cnt
from 
  (select * from light)
  , (select * from enhanced)
group by
  d, p

但是这个查询返回错误的计数(大约是两倍) 只有当我按两个字段分组时才会发生这种情况。单场效果很好。我发现当我将联合包装在另一个子查询中时它可以正常工作

select
  d
  , p
  ,count(1) - count(t) light_cnt
  ,count(t) enhanced_cnt
from
  (select * from 
      (select * from light)
      , (select * from enhanced)
  )
group by
  d, p

这是一个错误还是我做错了什么?


编辑:

我在没有group by 的情况下重现了相同的损坏行为,只是使用了where

select count(1) from enhanced where p = 124

返回 292

select count(1) from light where p = 124

返回 12512

select count(1)
from (select * from light), (select * from enhanced)
where p = 124

返回正确的 12804,而

select count(1), count(t)
from (select * from light), (select * from enhanced)
where p = 124

返回 24527, 501... 很奇怪。似乎是一个错误。

解决方法:

select count(1), count(t)
from (select * from (select * from light), (select * from enhanced))
where p = 124

返回 12804、292。正确。

lightenhanced 两个表都具有从 avro 继承的复杂模式。有记录和重复字段。为简单起见,字段pt 在上面的选择中采用缩写形式。实数是p -> record.record.record.id(叶子是整数)和t -> record.time(叶子是整数)。路径 pt 中的记录均不可重复。都可以为空。

【问题讨论】:

只是想调试一下。如果您只在两者中都执行 select count(*),那么计数之间是否存在差异? 表的结构是什么?任何重复/嵌套结构? @sjuul 这两个表的简单计数:select count(*) from light 返回 50607517,enhanced 返回 233162。而select sum(light_cnt) ,sum(enhanced_cnt) from([first query]) 返回 105536984 和 639161。从第二个查询中选择的总和是正确的。 @FelipeHoffa 是的,两个表都有嵌套和重复的结构。列的类型d是从整数秒到时间戳p是嵌套record.record.record.id整数,t也是嵌套record.time整数 【参考方案1】:

请参阅Difference in statistics from Google Analytics Report and BigQuery Data in Hive table,您可能会遇到类似的问题,因为您正在展平来自 2 个重复列的数据:这会产生 n*m 个结果。

证明这一点的查询:

SELECT col, x FROM (
  SELECT "wrong" col, SUM(totals.pageviews) x
  FROM (FLATTEN ([google.com:analytics-bigquery:LondonCycleHelmet.ga_sessions_20130910], hits))
), (
  SELECT "correct" col, SUM(totals.pageviews) x
  FROM [google.com:analytics-bigquery:LondonCycleHelmet.ga_sessions_20130910]
)

col     x    
wrong   2262     
correct 249 

准确显示您正在经历的问题的查询。所有结果数字都应该相同,但它们不同 - 结果取决于 BigQuery 做出的 FLATTEN() 选择。如果您想获得正确的数字,请在计数之前明确说明 BigQuery 应如何展平表格:

SELECT a, b, c    FROM (
SELECT COUNT(1)  a
FROM (SELECT * FROM [google.com:analytics-bigquery:LondonCycleHelmet.ga_sessions_20130910] ), (SELECT * FROM [google.com:analytics-bigquery:LondonCycleHelmet.ga_sessions_20130910] )
),(
SELECT COUNT(customDimensions.index) b
FROM (SELECT * FROM [google.com:analytics-bigquery:LondonCycleHelmet.ga_sessions_20130910] ), (SELECT * FROM [google.com:analytics-bigquery:LondonCycleHelmet.ga_sessions_20130910] )
),(
SELECT COUNT(hits.hitNumber) c
FROM (SELECT * FROM [google.com:analytics-bigquery:LondonCycleHelmet.ga_sessions_20130910] ), (SELECT * FROM [google.com:analytics-bigquery:LondonCycleHelmet.ga_sessions_20130910] )
),(
SELECT COUNT(1)  a, COUNT(customDimensions.index) b, COUNT(hits.hitNumber) c
FROM (SELECT * FROM [google.com:analytics-bigquery:LondonCycleHelmet.ga_sessions_20130910] ), (SELECT * FROM [google.com:analytics-bigquery:LondonCycleHelmet.ga_sessions_20130910] )
),(
SELECT COUNT(1)  a, COUNT(customDimensions.index) b
FROM (SELECT * FROM [google.com:analytics-bigquery:LondonCycleHelmet.ga_sessions_20130910] ), (SELECT * FROM [google.com:analytics-bigquery:LondonCycleHelmet.ga_sessions_20130910] )
),(
SELECT COUNT(1)  a, COUNT(hits.hitNumber) c
FROM (SELECT * FROM [google.com:analytics-bigquery:LondonCycleHelmet.ga_sessions_20130910] ), (SELECT * FROM [google.com:analytics-bigquery:LondonCycleHelmet.ga_sessions_20130910] )
),(
SELECT COUNT(customDimensions.index) b, COUNT(hits.hitNumber) c
FROM (SELECT * FROM [google.com:analytics-bigquery:LondonCycleHelmet.ga_sessions_20130910] ), (SELECT * FROM [google.com:analytics-bigquery:LondonCycleHelmet.ga_sessions_20130910] )
),(
SELECT COUNT(1) a, COUNT(customDimensions.index) b, COUNT(hits.hitNumber) c
FROM [google.com:analytics-bigquery:LondonCycleHelmet.ga_sessions_20130910], [google.com:analytics-bigquery:LondonCycleHelmet.ga_sessions_20130910])

Row a   b   c    
1   126          
2       510      
3           724  
4   126 102 766  
5   726 510      
6   126     724  
7       102 766  
8   126 102 724  

【讨论】:

感谢@Felipe,这在某种程度上很有帮助,但我仍然不明白我的解决方法是如何工作的。将子查询的联合包装在另一个子查询(更高一级)中是否对 bigquery 说“根本不扁平化”?我的意思是为什么SELECT count(1) a, COUNT(customDimensions.index) b, COUNT(hits.hitNumber) c FROM (Select * from (SELECT * FROM [google.com:analytics-bigquery:LondonCycleHelmet.ga_sessions_20130910] ), (SELECT * FROM [google.com:analytics-bigquery:LondonCycleHelmet.ga_sessions_20130910] )) 工作正常? 通过简单的观察,是的。但是为什么不选择没有那么多星星的简单版:SELECT COUNT(1) a, COUNT(customDimensions.index) b, COUNT(hits.hitNumber) c FROM [google.com:analytics-bigquery:LondonCycleHelmet.ga_sessions_20130910], [google.com:analytics-bigquery:LondonCycleHelmet.ga_sessions_20130910] 好的,在这个例子中就足够了,但是我有两个表,它们的模式略有不同,所以带有星号的子查询的联合可以统一它们。这是我必须想到的。

以上是关于bigquery:依靠子查询的联合的主要内容,如果未能解决你的问题,请参考以下文章

错误:语法错误:应为“)”,但在子查询中得到语句结束语句

BigQuery 为子查询返回 null

如何在 Datalab 的 api 中使用 Bigquery 中的子查询?

BIGQUERY:连接谓词中的表不受支持的子查询

MySQL的查询,子查询,联结查询,联合查询

Bigquery 将子查询应用于分区时间