Reputation: 47
I have three tables, t1, t2 and t3. Table structure and values:
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
So with normal SQL I can join t1 and t2 on t1_k1 = t2_k1 and t2 and t3 on t2_k2 = t3_k2, that is:
SELECT t1_val, t2_val, t3_val
FROM t1, t2, t3
WHERE t1_k1 = t2_k1 AND t2_k2 = t3_k2
To get
t1foo | t2foo | t3foo
t1bar | t2bar | t3bar
t1baz | t2baz | t3baz
Now I'm trying to get the same result with bigQuery SQL. From my understanding, using CROSS JOIN should work just like the comma in regular SQL, so I thought the following would work:
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
But I get an error that "Field 't3_k2' not found on either side of the JOIN". Adding parentheses like this:
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
gives a (frankly quite cryptic) syntax error 'Encountered "" at line 0, column 0.' With just two tables CROSS JOIN works, but then it's no different from a normal JOIN. I haven't found examples using CROSS JOIN on more than two tables. Is it possible? Am I doing something wrong?
Upvotes: 1
Views: 3997
Reputation: 21
Maybe it changed in the last 6 years, but now using commas as a CROSS JOIN works, you only need to be careful with ambiguity.
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
The above query results in:
t1foo | t2foo | t3foo
t1bar | t2bar | t3bar
t1baz | t2baz | t3baz
You can copy and paste to check.
But, yes, in this specific example it would be better to use a INNER JOIN as Michael and Mikhail pointed out.
Upvotes: 0
Reputation: 47
So it turns out it's all a matter of defining table aliases, see the other question for an example: CROSS JOIN: only two tables?.
Upvotes: 0
Reputation: 7724
As Mikhail noticed in his answer, you don't need CROSS JOIN, regular JOIN works fine. Here is how to do it in one statement, without multilevel JOINs:
I used inline SELECT statements to provide data for 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
Upvotes: 0
Reputation: 172954
Try below
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
Note: I think your example is just tailored to address your CROSS JOIN issue - but wanted to mention that if your example really represents your issue - you do not need CROSS JOIN - rather you need [INNER] JOIN, as in below
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
Added runnable example for second query - to prove it works :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
Upvotes: 4