交叉连接两个以上的表

问题描述 投票:0回答:5

我有三个表,t1、t2 和 t3。表结构和值:

t1_id | t1_k1 | t1_val
------+-------+--------
1     | k1foo | t1foo
2     | k1bar | t1bar
3     | k1baz | t1baz

t2_id | t2_k1 | t2_k2 | t2_val
------+-------+-------+--------
1     | k1foo | k2foo | t2foo
2     | k1bar | k2bar | t2bar
3     | k1baz | k2baz | t2baz

t3_id | t3_k2 | t3_val
------+-------+--------
1     | k2foo | t3foo
2     | k2bar | t3bar
3     | k2baz | t3baz

因此,使用普通 SQL,我可以在 t1_k1 = t2_k1 上连接 t1 和 t2,在 t2_k2 = t3_k2 上连接 t2 和 t3,即:

SELECT t1_val, t2_val, t3_val
FROM t1, t2, t3
WHERE t1_k1 = t2_k1 AND t2_k2 = t3_k2

获取

t1foo | t2foo | t3foo
t1bar | t2bar | t3bar
t1baz | t2baz | t3baz

现在我尝试使用 bigQuery SQL 获得相同的结果。根据我的理解,使用 CROSS JOIN 应该像常规 SQL 中的逗号一样工作,所以我认为以下内容可以工作:

SELECT t1_val, t2_val, t3_val
FROM test.t1 CROSS JOIN test.t2 CROSS JOIN test.t3
WHERE t1_k1 = t2_k1 AND t2_k2 = t3_k2

但是我收到错误“在 JOIN 的任一侧都找不到字段 't3_k2'”。 像这样添加括号:

SELECT SELECT t1_val, t2_val, t3_val
FROM ((test.t1 CROSS JOIN test.t2) CROSS JOIN test.t3)
WHERE t1_k1 = t2_k1 AND t2_k2 = t3_k2

给出一个(坦率地说相当神秘的)语法错误“在第 0 行第 0 列遇到“”。” 只需两个表,CROSS JOIN 就可以工作,但它与普通 JOIN 没有什么不同。 我还没有找到在两个以上的表上使用 CROSS JOIN 的示例。是否可以?我是不是做错了什么?

google-bigquery
5个回答
4
投票

尝试以下

SELECT t1_val, t2_val, t3_val 
FROM (
  SELECT t1_val, t2_val, t2_k2
  FROM test.t1 AS a 
  CROSS JOIN test.t2 AS b
  WHERE t1_k1 = t2_k1 
) AS c
CROSS JOIN test.t3 AS d
WHERE t2_k2 = t3_k2

注意:我认为您的示例只是为了解决您的 CROSS JOIN 问题而定制的 - 但想提一下,如果您的示例确实代表了您的问题 - 您不需要 CROSS JOIN - 相反,您需要 [INNER] JOIN,如下所示

SELECT t1_val, t2_val, t3_val
FROM (
  SELECT t1_val, t2_val, t2_k2
  FROM test.t1 AS a JOIN test.t2 AS b
  ON t1_k1 = t2_k1 
) AS c
JOIN test.t3 AS d ON t2_k2 = t3_k2

为第二个查询添加了可运行示例 - 以证明它有效:o)

SELECT t1_val, t2_val, t3_val
FROM (
  SELECT t1_val, t2_val, t2_k2
  FROM (
    SELECT * FROM 
    (SELECT 1 AS t1_id, 'k1foo' AS t1_k1, 't1foo' AS t1_val),
    (SELECT 2 AS t1_id, 'k1bar' AS t1_k1, 't1bar' AS t1_val),
    (SELECT 3 AS t1_id, 'k1baz' AS t1_k1, 't1baz' AS t1_val)
  ) AS a 
  JOIN (
    SELECT * FROM 
    (SELECT 1 AS t2_id, 'k1foo' AS t2_k1, 'k2foo' AS t2_k2, 't2foo' AS t2_val),
    (SELECT 2 AS t2_id, 'k1bar' AS t2_k1, 'k2bar' AS t2_k2, 't2bar' AS t2_val),
    (SELECT 3 AS t2_id, 'k1baz' AS t2_k1, 'k2baz' AS t2_k2, 't2baz' AS t2_val)
  ) AS b
  ON t1_k1 = t2_k1 
) as c
JOIN (
  SELECT * FROM 
  (SELECT 1 AS t3_id, 'k2foo' AS t3_k2, 't3foo' AS t3_val),
  (SELECT 2 AS t3_id, 'k2bar' AS t3_k2, 't3bar' AS t3_val),
  (SELECT 3 AS t3_id, 'k2baz' AS t3_k2, 't3baz' AS t3_val)
) AS d
ON t2_k2 = t3_k2

0
投票

正如 Mikhail 在他的回答中注意到的那样,你不需要 CROSS JOIN,常规 JOIN 就可以了。以下是如何在一条语句中完成此操作,无需多级 JOIN:

我使用内联 SELECT 语句为 t1、t2、t3 提供数据:

SELECT t1_val, t2_val, t3.t3_val as t3_val
FROM (SELECT 1 as t1_id, "k1foo" as t1_k1, "t1foo" as t1_val) t1
JOIN (SELECT 1 as t2_id, "k1foo" as t2_k1, "k2foo" as t2_k2, "t2foo" as t2_val) t2
ON t1_k1 = t2_k1 
JOIN (SELECT 1 as t3_id, "k2foo" as t3_k2, "t3foo" as t3_val) t3
ON t2_k2 = t3_k2

0
投票

所以事实证明这都是定义表别名的问题,请参阅另一个问题的示例:CROSS JOIN:只有两个表?.


0
投票

也许在过去的6年里它发生了变化,但现在使用逗号作为CROSS JOIN的作品,你只需要小心歧义即可。

SELECT 
  t1_val, 
  t2_val, 
  t3_val
FROM (
  SELECT * FROM 
  (SELECT 1 AS t1_id, 'k1foo' AS t1_k1, 't1foo' AS t1_val) UNION ALL
  (SELECT 2 AS t1_id, 'k1bar' AS t1_k1, 't1bar' AS t1_val) UNION ALL
  (SELECT 3 AS t1_id, 'k1baz' AS t1_k1, 't1baz' AS t1_val)
) AS a
,(
  SELECT * FROM 
  (SELECT 1 AS t2_id, 'k1foo' AS t2_k1, 'k2foo' AS t2_k2, 't2foo' AS t2_val) UNION ALL
  (SELECT 2 AS t2_id, 'k1bar' AS t2_k1, 'k2bar' AS t2_k2, 't2bar' AS t2_val) UNION ALL
  (SELECT 3 AS t2_id, 'k1baz' AS t2_k1, 'k2baz' AS t2_k2, 't2baz' AS t2_val)
) AS b
,(
  SELECT * FROM 
  (SELECT 1 AS t3_id, 'k2foo' AS t3_k2, 't3foo' AS t3_val) UNION ALL
  (SELECT 2 AS t3_id, 'k2bar' AS t3_k2, 't3bar' AS t3_val) UNION ALL
  (SELECT 3 AS t3_id, 'k2baz' AS t3_k2, 't3baz' AS t3_val)
) AS c
where
  a.t1_k1 = b.t2_k1 
  AND b.t2_k2 = c.t3_k2

以上查询结果为:

t1foo | t2foo | t3foo
t1bar | t2bar | t3bar
t1baz | t2baz | t3baz

您可以复制粘贴来查看。


但是,是的,在这个具体示例中,最好使用 Michael 和 Mikhail 指出的 INNER JOIN。


0
投票

我自己也遇到了这个问题,并通过执行以下操作非常简单地解决了它:

SELECT     
   shirts.shirt_color,   
   pants.pants_color,   
   socks.sock_color 
FROM 
   shirts   
   CROSS JOIN pants   
   CROSS JOIN socks;

这些似乎对我在 BQ 有用

来源:https://discuss.codecademy.com/t/can-you-cross-join-on-more-than-two-tables/356104

© www.soinside.com 2019 - 2024. All rights reserved.