这个问题不是要解决一个特定的问题,而是要了解用于压扁数组的常见SQL习惯用法背后的实际情况。幕后有一些魔力,我想偷看句法糖的幕后,看看发生了什么。
让我们考虑下表t1
:
现在让我们假设我们有一个名为FLATTEN
的函数,它接受一个类型数组的列并解压缩该列中的每个数组,这样我们就为每个数组中的每个值留下一行 - 如果我们运行SELECT FLATTEN(numbers_array) AS flattened_numbers FROM t1
,我们期待以下内容,我们称之为t2
在SQL中,CROSS JOIN通过将第一个表中的每一行与第二个表中的每一行组合来组合来自两个表的行。因此,如果我们运行SELECT id, flattened.flattened_numbers from t1 CROSS JOIN flattened
,我们就会获得
现在flatten只是一个虚构的函数,你可以看到将它与CROSS JOIN结合起来并不是很有用,因为id
列的每个原始值都与flattened_numbers
混合在一起来自每个原始行。由于我们没有WHERE
子句只选择我们想要的CROSS JOIN
行,所以一切都变得混乱了。
人们实际用于展平数组的模式如下所示:
SELECT id, flattened_numbers FROM t1 CROSS JOIN UNNEST(sequences.some_numbers) AS flattened_numbers
,生成
但我不明白为什么CROSS JOIN UNNEST
模式确实有效。因为CROSS JOIN
不包含WHERE
子句,所以我希望它的行为就像我上面概述的FLATTEN
函数一样,其中每个unnested值都与{{1 }}
有人可以“解包”t1
模式中实际发生的事情,确保每一行只与其自己的嵌套值相连(而不是其他行的嵌套值)?
答案 0 :(得分:6)
考虑这个问题的最佳方法是查看逐行发生的情况。设置一些输入数据,我们有:
WITH t1 AS (
SELECT 1 AS id, [0, 1] AS numbers_array UNION ALL
SELECT 2, [2, 4, 5]
)
...
(我在第二行使用第三个元素来使事情变得更有趣)。如果我们只是从中选择,我们得到如下输出:
WITH t1 AS (
SELECT 1 AS id, [0, 1] AS numbers_array UNION ALL
SELECT 2, [2, 4, 5]
)
SELECT * FROM t1;
+----+---------------+
| id | numbers_array |
+----+---------------+
| 1 | [0, 1] |
| 2 | [2, 4, 5] |
+----+---------------+
现在让我们谈谈取消。 UNNEST
函数接受一个数组并返回数组元素类型的值表。大多数BigQuery表是定义为列集合的SQL表,而值表包含一些 value 类型的行。对于numbers_array
,UNNEST(numbers_array)
返回值类型为INT64
的值表,因为numbers_array
是一个元素类型为INT64
的数组。此值表包含numbers_array
中t1
当前行的id
中的所有元素。
对于UNNEST(numbers_array)
为1的行,+-----+
| f0_ |
+-----+
| 0 |
| 1 |
+-----+
返回的值表的内容为:
SELECT * FROM UNNEST([0, 1]);
这与我们使用以下查询得到的相同:
UNNEST([0, 1])
在这种情况下, INT64
表示"根据0
值1
和id
"创建一个值表。
同样,对于UNNEST(numbers_array)
为2的行,+-----+
| f0_ |
+-----+
| 2 |
| 4 |
| 5 |
+-----+
返回的值表的内容为:
CROSS JOIN
现在让我们谈谈CROSS JOIN
如何适应图片。在大多数情况下,您在两个不相关的表之间使用CROSS JOIN
。换句话说,UNNEST
右侧表格的内容未由左侧表格的当前内容定义。
对于数组和UNNEST(numbers_array)
,t1
生成的值表的内容会根据t1
的当前行而更改。当我们加入这两个表时,我们得到UNNEST(numbers_array)
的当前行与WITH t1 AS (
SELECT 1 AS id, [0, 1] AS numbers_array UNION ALL
SELECT 2, [2, 4, 5]
)
SELECT id, number
FROM t1
CROSS JOIN UNNEST(numbers_array) AS number;
+----+--------+
| id | number |
+----+--------+
| 1 | 0 |
| 1 | 1 |
| 2 | 2 |
| 2 | 4 |
| 2 | 5 |
+----+--------+
的所有行的叉积。例如:
numbers_array
2 + 3 = 5
在第一行有两个元素,第二行有三个元素,因此我们在查询结果中得到numbers_array
行。
要回答有关如何与展开CROSS JOIN
和然后执行WITH t1 AS (
SELECT 1 AS id, [0, 1] AS numbers_array UNION ALL
SELECT 2, [2, 4, 5]
), t2 AS (
SELECT number
FROM t1
CROSS JOIN UNNEST(numbers_array) AS number
)
SELECT number
FROM t2;
+--------+
| number |
+--------+
| 0 |
| 1 |
| 2 |
| 4 |
| 5 |
+--------+
不同的问题,请查看此查询的结果:< / p>
t2
在这种情况下,number
是一个SQL表,其中包含名为CROSS JOIN
的列,并带有这些值。如果我们在t1
和t2
之间执行WITH t1 AS (
SELECT 1 AS id, [0, 1] AS numbers_array UNION ALL
SELECT 2, [2, 4, 5]
), t2 AS (
SELECT number
FROM t1
CROSS JOIN UNNEST(numbers_array) AS number
)
SELECT id, numbers_array, number
FROM t1
CROSS JOIN t2;
+----+---------------+--------+
| id | numbers_array | number |
+----+---------------+--------+
| 1 | [0, 1] | 0 |
| 1 | [0, 1] | 1 |
| 1 | [0, 1] | 2 |
| 1 | [0, 1] | 4 |
| 1 | [0, 1] | 5 |
| 2 | [2, 4, 5] | 0 |
| 2 | [2, 4, 5] | 1 |
| 2 | [2, 4, 5] | 2 |
| 2 | [2, 4, 5] | 4 |
| 2 | [2, 4, 5] | 5 |
+----+---------------+--------+
,我们会得到所有行的真实叉积:
CROSS JOIN UNNEST(numbers_array)
那么这与前一个t2
查询的区别是什么?在这种情况下,t1
的内容不会因t1
的每一行而发生变化。对于t2
中的第一行,t1
中有五行。对于t2
中的第二行,CROSS JOIN
中有五行。因此,两者之间的5 + 5 = 10
总共返回import React from "react";
import { render } from "react-dom";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
const ParamsExample = () => (
<Router>
<div>
<h2>Accounts</h2>
<ul>
<li><Link to={`/${encodeURI("%netflix")}`}>Netflix</Link></li>
<li><Link to="/zillow-group">Zillow Group</Link></li>
<li><Link to="/yahoo">Yahoo</Link></li>
<li><Link to="/modus-create">Modus Create</Link></li>
</ul>
<Route path="/:id" component={Child} />
</div>
</Router>
)
const Child = ({ match }) => (
<div>
<h3>ID: {match.params.id}</h3>
</div>
)
render(<ParamsExample />, document.getElementById("react"));
行。