我有两张桌子。
表1是一个整数的COLUMN。
表2有三个COLUMNS:start_integer,end_integer,data
简单查询是将整数列与数据
连接起来 integer >= start_integer AND integer <= end_integer
在许多SQL实现中,这可以使用左条件JOIN ... ON BETWEEN
来完成SELECT tbl1.integer, tbl2.data FROM tbl1
LEFT JOIN tbl2 ON tbl1.integer BETWEEN tbl2.start_integer AND
tbl2.end_integer;
但似乎BigQuery只支持JOIN ON而只有一个=条件。
这可以通过交叉连接来完成,但BigQuery抱怨我的表太大了。 CROSS JOIN EACH无效。
如何在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运算符的右侧表必须是一个小表。如果左侧表较小,则切换表;如果两个表都大于http://goo.gl/wXqgHs中描述的最大值,则使用JOIN EACH。
答案 0 :(得分:5)
好消息(2016)! BigQuery现在支持不等式连接 - 确保取消选中&#34;使用旧SQL选项&#34;。
示例查询:
SELECT *
FROM (
SELECT 1 x
) a JOIN (
SELECT 2 y
) b
ON a.x<b.y
使用旧版SQL:
Error: ON clause must be AND of = comparisons of one field name from each table, ...
使用标准SQL:
1 2
答案 1 :(得分:2)
BigQuery不支持右侧表的交叉连接。
答案 2 :(得分:0)
只是添加我如何做这个问题的大纲 - 有点hacky但是最快的方式我发现这个很好。
输入表如下:
{
"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部分作为减少搜索空间的方式(我的查找表中的from和to范围不会扩展到具有不同的第1部分和第2部分的范围) - 如果是这样,这种方法失败了)。
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
所以它基本上吹掉了数据(通过ip地址的第1部分和第2部分的相等连接以及ip_from和ip_to地址),然后通过使用if between语句将其减少到组(执行此操作而不是where条件)确保您获得正确的左外连接,这样您还可以查看您处理的但在查找表中没有信息的记录。
Defo不是最漂亮的,可能还有一两种方法可以优化它,但现在正在为我工作,并在10-20秒内查找500K输入IP地址对16M记录的查找表。
答案 3 :(得分:-1)
您是否尝试过以下查询:
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;