Sql bigquery中的条件联接

Sql bigquery中的条件联接,sql,join,google-bigquery,Sql,Join,Google Bigquery,我有两张桌子 表1是一列整数 表2有三列:开始整数、结束整数、数据 简单的查询是将整数列与其中的数据连接起来 integer >= start_integer AND integer <= end_integer 但BigQuery似乎只支持带有=条件的连接 这可以通过交叉连接来实现,但是BigQuery抱怨我的表太大了。交叉连接无效 如何在BigQuery的SQL限制内完成此连接任务 下面是我的BigQuery SQL: SELECT tbl1.integer, tbl2.d

我有两张桌子

表1是一列整数

表2有三列:开始整数、结束整数、数据

简单的查询是将整数列与其中的数据连接起来

  integer >= start_integer AND integer <= end_integer
但BigQuery似乎只支持带有=条件的连接

这可以通过交叉连接来实现,但是BigQuery抱怨我的表太大了。交叉连接无效

如何在BigQuery的SQL限制内完成此连接任务

下面是我的BigQuery SQL:

SELECT tbl1.integer, tbl2.data
FROM bq:data.tbl1 
CROSS JOIN bq:data.tbl2
WHERE tbl1.integer BETWEEN tbl2.start_integer AND tbl2.end_integer;
返回错误:

错误:4.1-4.132:联接运算符的右侧表必须是一个小表。如果左侧表较小,则切换表;如果两个表都大于中所述的最大值,则使用JOIN EACH


您是否尝试了以下查询:

SELECT tbl1.integer, tbl2.data
FROM bq:data.tbl1 
JOIN EACH bq:data.tbl2
ON tbl1.integer >= tbl2.start_integer AND tbl1.integer <= tbl2.end_integer;
选择tbl1.integer,tbl2.data
来自bq:data.tbl1
加入每个bq:data.tbl2

在tbl1.integer>=tbl2.start\u integer和tbl1.integer上,BigQuery不支持右侧表上的交叉联接。

好消息(2016)!BigQuery现在确实支持不平等联接-请确保取消选中“使用遗留SQL选项”

查询示例:

SELECT * 
FROM (
  SELECT 1 x
) a JOIN (
  SELECT 2 y
) b
ON a.x<b.y
使用标准SQL:

1     2

  • 文件:
  • 讨论:

只是简单地介绍一下我是如何解决这个问题的——有点粗糙,但这是我发现的最快的方法,可以很好地扩展

输入表如下所示:

{
    "ip": "130.211.149.140",
    "ip_int": "2194904460",
    "ip_part1": "130",
    "ip_part2": "211",
    "ip_part3": "149",
    "ip_part4": "140",
    "num_requests": "6811"
  }
查找表如下所示:

{
    "de_ip_key": "DE18_92.66.156.93_92.66.156.112",
    "ip_key": "92.66.156.93_92.66.156.112",
    "ip_from_int": "1547869277",
    "ip_to_int": "1547869296",
    "ip_from": "92.66.156.93",
    "ip_to": "92.66.156.112",
    "naics_code": "518210",
    "ip_from_part1": "92",
    "ip_from_part2": "66",
    "ip_from_part3": "156",
    "ip_from_part4": "93",
    "ip_to_part1": "92",
    "ip_to_part2": "66",
    "ip_to_part3": "156",
    "ip_to_part4": "112"
  }
因此,使用ip地址的第1部分和第2部分进行连接,以减少搜索空间(我的查找表中的“从”和“到”范围的范围往往不会宽到有不同的第1部分和第2部分-如果这样,这种方法会失败)

因此,它基本上会吹出数据(通过ip地址的第1部分和第2部分上的相等连接以及ip_from和ip_to addresses),然后使用if-between语句在组上减少数据(这样做而不是where条件可以确保获得正确的左外部联接,以便还可以查看哪些记录已处理,但在查找表中没有任何信息)


Defo不是最漂亮的,可能还有一种或两种以上的方法来优化它,但现在正在为我工作,在10-20秒内根据16M记录的查找表查找500K输入ip地址。

您的中间需要移动到何处,并使用交叉连接。根据文档,交叉连接操作可以返回大量数据。如果交叉查询不起作用,请发布交叉查询。交叉连接查询和错误发布中没有每个。数据的性质是什么?根据问题的性质,可能有一个很好的解决方法。IP地址列表和与一系列IP地址关联的数据。我也有这个确切的问题。可以使用UDF将每个ip映射到正确表中的一个范围?BigQuery不支持连接中的等式。2016年更新:新的BigQuery SQL确实支持连接中的不等式-取消选中“遗留SQL”。)哦,太好了,只是花了一天的时间试图解决R中的数据表的问题。迫不及待地想查看它。
{
    "ip": "130.211.149.140",
    "ip_int": "2194904460",
    "ip_part1": "130",
    "ip_part2": "211",
    "ip_part3": "149",
    "ip_part4": "140",
    "num_requests": "6811"
  }
{
    "de_ip_key": "DE18_92.66.156.93_92.66.156.112",
    "ip_key": "92.66.156.93_92.66.156.112",
    "ip_from_int": "1547869277",
    "ip_to_int": "1547869296",
    "ip_from": "92.66.156.93",
    "ip_to": "92.66.156.112",
    "naics_code": "518210",
    "ip_from_part1": "92",
    "ip_from_part2": "66",
    "ip_from_part3": "156",
    "ip_from_part4": "93",
    "ip_to_part1": "92",
    "ip_to_part2": "66",
    "ip_to_part3": "156",
    "ip_to_part4": "112"
  }
select
  ip,
  ip_int,
  -- pick first info from de
  first(ip_key) as ip_key,
  first(de_ip_key) as de_ip_key,
  first(naics_code) as naics_code
from
  (
  select 
    ip as ip,
    ip_int as ip_int,
    ip_key as ip_key,
    de_ip_key as de_ip_key,
    naics_code as naics_code,
  from 
    -- join based on part 1 and 2 of ip from range
    (
    select 
      input.ip as ip,
      input.ip_int as ip_int,
      if(input.ip_int between de.ip_from_int and de.ip_to_int,de.ip_key,null) as ip_key,
      if(input.ip_int between de.ip_from_int and de.ip_to_int,de.de_ip_key,null) as de_ip_key,
      if(input.ip_int between de.ip_from_int and de.ip_to_int,de.naics_code,null) as naics_code,
    from
      [ip.lookup_input_tbl]  input
    left outer join each 
      [digital_element.data_naics_code] de
    on
      input.ip_part1=de.ip_from_part1
      and
      input.ip_part2=de.ip_from_part2
    group by 1,2,3,4,5
    ),
    -- join based on part 1 and 2 of ip to range
    (
    select 
      input.ip as ip,
      input.ip_int as ip_int,
      if(input.ip_int between de.ip_from_int and de.ip_to_int,de.ip_key,null) as ip_key,
      if(input.ip_int between de.ip_from_int and de.ip_to_int,de.de_ip_key,null) as de_ip_key,
      if(input.ip_int between de.ip_from_int and de.ip_to_int,de.naics_code,null) as naics_code,
    from
      [ip.lookup_input_tbl]  input
    left outer join each 
      [digital_element.data_naics_code] de
    on
      input.ip_part1=de.ip_to_part1
      and
      input.ip_part2=de.ip_to_part2
    group by 1,2,3,4,5
    ),
  group by 1,2,3,4,5
  -- order so null records from either join go to bottom and get left behind on the first group by
  order by ip_int,ip_key desc
  )
group by 1,2