SQL 参考

SELECT 语法

师成师成· 更新于 2026-09-28· 阅读 49 分钟· 0 次阅读

登录后可跨设备保存划线和私人笔记登录

SELECT 语法

DataFusion 中的查询会从表、子查询、表函数或字面量值中扫描数据,并返回零行或多行结果。DataFusion 支持如下形式的 SELECT 查询,其中的子句均为可选,可以省略。点击相应链接可查看各子句的详细介绍。

[ WITH cte [, ...] ]
SELECT select_item [, ...]
[ INTO table_name ]
[ FROM from_item [, ...] ]
[ JOIN join_item ... ]
[ WHERE condition ]
[ GROUP BY grouping_element [, ...] | GROUP BY ALL ]
[ HAVING condition ]
[ WINDOW window_name AS (window_definition) [, ...] ]
[ QUALIFY condition ]
[ { UNION | INTERSECT | EXCEPT } query ] [...]
[ ORDER BY order_expression [, ...] ]
[ LIMIT count ] [ OFFSET count ]
[ |> pipe_operator ... ]

SQL 查询中未加引号的标识符会转换为小写,但推断出的 schema 字段名不会被更改。如果字段名包含大写字母或其他需要加引号的字符,请使用双引号引用它。参见此示例以作说明。

WITH 子句

WITH [RECURSIVE] cte_name [(column_name [, ...])] AS (query) [, ...]

WITH 子句用于定义公用表表达式(CTEs),这些表达式可以在查询的其余部分按名称引用。

示例:

WITH x AS (SELECT a, MAX(b) AS b FROM t GROUP BY a)
SELECT a, b FROM x;

CTE 也可以对其输出列进行重命名:

WITH x(key, total) AS (
  SELECT a, SUM(b) FROM t GROUP BY a
)
SELECT key, total FROM x;

DataFusion 支持使用 WITH RECURSIVE 定义递归 CTE。递归 CTE 的支持由配置项 datafusion.execution.enable_recursive_ctes 控制,默认情况下已启用。

WITH RECURSIVE numbers AS (
  SELECT 1 AS n
  UNION ALL
  SELECT n + 1 FROM numbers WHERE n < 3
)
SELECT n FROM numbers;

SELECT 子句

SELECT [ALL | DISTINCT | DISTINCT ON (expression [, ...])]
       select_item [, ...]
       [INTO table_name]

SELECT 列表中可以包含列引用、任意表达式、标量函数、聚合函数、窗口函数、标量子查询以及通配符。

示例:

SELECT a, b, a + b AS sum_ab FROM table_name;

别名可以带 AS,也可以不带 AS 书写:

SELECT a AS key, b value FROM table_name;

当所选表达式不需要输入行时,SELECT 可以不带 FROM 子句使用:

SELECT 1 + 2 AS three;

SELECT * 需要 FROM 子句。

DISTINCT

SELECT DISTINCT select_item [, ...]
SELECT DISTINCT ON (expression [, ...]) select_item [, ...]

默认情况下,SELECT 使用 ALL 语义,返回每一行。DISTINCT 限定符会从查询结果中删除重复的行。

示例:

SELECT DISTINCT person, age FROM employees;

DataFusion 还支持 PostgreSQL 风格的 DISTINCT ON,它会为所列表达式的每个不同值保留一行。使用 ORDER BY 来选择每个分组中保留哪一行。当存在 ORDER BY 时,最前面的 ORDER BY 表达式必须与 DISTINCT ON 表达式相匹配。

如果多行具有相同的 DISTINCT ON 值,而 ORDER BY 子句并未对这些行给出完全的排序,则保留哪一行是未定义的。可以添加额外的 ORDER BY 表达式,使选择结果保持确定。

SELECT DISTINCT ON (customer_id) customer_id, order_id, order_date
FROM orders
ORDER BY customer_id, order_date DESC;

通配符

*
table_alias.*
* EXCLUDE column_name
* EXCLUDE (column_name [, ...])
* EXCEPT column_name
* EXCEPT (column_name [, ...])
* REPLACE (expression AS column_name [, ...])

使用 * 选择所有列,或使用 table_alias.* 选择某个特定输入的所有列。

示例:

SELECT * FROM orders;
SELECT o.* FROM orders AS o;

通配符投影支持 EXCLUDE 和 EXCEPT 来省略列。两者都可接受单个列名,或带括号的列名列表。

SELECT * EXCLUDE customer_id FROM orders;
SELECT * EXCLUDE (customer_id, internal_note) FROM orders;
SELECT * EXCEPT customer_id FROM orders;
SELECT * EXCEPT (customer_id, internal_note) FROM orders;
SELECT o.* EXCLUDE (internal_note) FROM orders AS o;

EXCLUDE 或 EXCEPT 列表中的每个名称都必须指向一个已存在的列。列表中不得重复指定同一个列,且通配符展开后不能得到零个列。

通配符投影还支持 REPLACE,它保留原有的列名,但用新的表达式替换该列。

SELECT * REPLACE (price * 2 AS price) FROM products;
SELECT p.* REPLACE (price * 2 AS price, product_id + 1000 AS product_id)
FROM products AS p;

RENAME 以及 * AS alias 这类通配符别名不受支持。

SELECT INTO

SELECT select_item [, ...] INTO table_name FROM ...

SELECT ... INTO table_name 会根据查询结果创建一个内存表。它与 CREATE TABLE ... AS SELECT 类似。

SELECT customer_id, SUM(amount) AS total
INTO customer_totals
FROM orders
GROUP BY customer_id;

FROM 子句

FROM from_item [, ...]

from_item:
  table_name [[AS] alias [(column_alias [, ...])]]
| (query) [[AS] alias [(column_alias [, ...])]]
| VALUES (expression [, ...]) [, ...] [[AS] alias [(column_alias [, ...])]]
| table_function(argument [, ...]) [[AS] alias [(column_alias [, ...])]]
| UNNEST(expression) [[AS] alias [(column_alias [, ...])]]

FROM 子句指定查询的输入关系。支持的输入包括表、CTE(公共表表达式)、派生表、VALUES、表函数和 UNNEST。

示例:

SELECT t.a FROM table_name AS t;

表别名可以包含列别名:

SELECT x, y
FROM some_table AS t(x, y);

子查询可以用在 FROM 子句中:

SELECT q.a
FROM (SELECT a FROM table_name WHERE a > 10) AS q;

VALUES 可以用作表表达式:

SELECT *
FROM VALUES (1, 'a'), (2, 'b') AS t(id, label);

range 和 generate_series 等表函数可以在 FROM 中使用:

SELECT value FROM range(0, 3);

UNNEST 将列表、数组或类似的嵌套值展开为每个元素一行。它可以用在 SELECT 列表中,对每个输入行的值进行展开;也可以用作 FROM 中的输入关系。在 FROM 中使用时,可以指定表别名和列别名。

SELECT * FROM UNNEST([1, 2, 3]) AS u(value);

要为每个输入行展开一个列,请在 SELECT 列表中使用 UNNEST:

SELECT id, UNNEST(items) FROM orders;

FROM 子句中的 UNNEST 目前尚不能引用前面 FROM 项的列(目前尚不支持隐式 lateral 引用,例如 FROM orders AS t, UNNEST(t.items))。

unnest_outer

unnest_outer(col) 是 UNNEST(col) 的外层 unnest 对应形式。二者仅在如何处理 NULL 和空输入列表方面有所不同:

形式NULL 输入列表空输入列表
UNNEST(col)丢弃丢弃
unnest_outer(col)一个 NULL 行一个 NULL 行
SELECT id, unnest_outer(tags) AS tag FROM rows;

tags 数组为空或为 NULL 的输入行会产生一行输出,其 tag 为 NULL,而不会被丢弃。这类似于其他引擎提供的外部展开变体(Spark 的 explode_outer、Hive 的 EXPLODE OUTER、Snowflake 的 FLATTEN(OUTER => true))。

unnest_outer 不能与 unnest 在同一个 SELECT 中混用——展开计划节点为其所有输出列只携带一种空值处理模式,因此混合使用会产生歧义。在这种情况下,规划器会返回错误。

WHERE 子句

WHERE condition

WHERE 子句在分组、聚合和窗口处理之前过滤输入行。

SELECT a FROM table_name WHERE a > 10;

JOIN 子句

from_item [join_type] JOIN from_item [join_condition]
from_item ASOF JOIN from_item MATCH_CONDITION (condition) [join_condition]
from_item CROSS JOIN from_item
from_item NATURAL JOIN from_item
from_item [join_type] JOIN LATERAL (query) AS alias [join_condition]
from_item, LATERAL (query) AS alias

join_type:
  INNER
| LEFT [OUTER]
| RIGHT [OUTER]
| FULL [OUTER]
| LEFT SEMI
| RIGHT SEMI
| LEFT ANTI
| RIGHT ANTI

join_condition:
  ON condition
| USING (column_name [, ...])

联接写在 FROM 子句中的输入关系之间。

联接条件可以使用 ON 或 USING。

示例:

SELECT *
FROM orders AS o
JOIN customers AS c ON o.customer_id = c.id;

SELECT *
FROM orders
JOIN customers USING (customer_id);

下面的连接示例使用此表:

select * from x;
+----------+----------+
| column_1 | column_2 |
+----------+----------+
| 1        | 2        |
+----------+----------+

INNER JOIN

关键字 JOIN 或 INNER JOIN 定义的连接只显示在两个表中都存在匹配的行。

SELECT * FROM x INNER JOIN x AS y ON x.column_1 = y.column_1;
+----------+----------+----------+----------+
| column_1 | column_2 | column_1 | column_2 |
+----------+----------+----------+----------+
| 1        | 2        | 1        | 2        |
+----------+----------+----------+----------+

同样的行为也可以通过在 FROM 子句中列出两个输入、并把连接条件放在 WHERE 子句中来实现:

SELECT * FROM x, x AS y WHERE x.column_1 = y.column_1;

左外连接

关键字 LEFT JOIN 或 LEFT OUTER JOIN 定义了一种连接,它包含左表的所有行,即使右表中没有匹配的行。当没有匹配时,连接的右侧会产生空值(null)。

SELECT * FROM x LEFT JOIN x AS y ON x.column_1 = y.column_2;
+----------+----------+----------+----------+
| column_1 | column_2 | column_1 | column_2 |
+----------+----------+----------+----------+
| 1        | 2        |          |          |
+----------+----------+----------+----------+

ASOF JOIN

DataFusion 遵循 Snowflake 的 ASOF JOIN 语法。ASOF JOIN 会根据有序比较,将每一行左表记录与至多一行右表记录进行匹配。它保留所有左表行,当没有匹配的右表行时,右表各列以 NULL 填充。

SELECT t.*, p.price
FROM trades AS t
ASOF JOIN prices AS p
MATCH_CONDITION (t.ts >= p.ts)
ON t.symbol = p.symbol;

MATCH_CONDITION 必须使用下列运算符之一,将左输入的一个表达式与右输入的一个表达式进行比较。操作数的顺序很重要:左输入的表达式必须位于左侧。

条件选中的右侧行
l >= r小于或等于 l 的最大 r
l > r严格小于 l 的最大 r
l <= r大于或等于 l 的最小 r
l < r严格大于 l 的最小 r

可选的 ON 子句(包含通过 AND 组合的等值条件)或 USING 子句,会在有序匹配之前将行划分为等值分组。不带限定的 USING 键在通配符输出中只出现一次,而两侧带限定的输入键仍然都可以引用。

如果没有等值键,所有行都属于同一个分组。初始执行策略会收集一个有序的右侧分区,并在每个左侧分区之间共享它,因此输出分区跟随左输入。完整的右输入必须能够放入内存,并且可能在每个左侧分区中被扫描一次;目前尚不支持溢写(spilling)和重分区的 ASOF 执行。

有序表达式或任意等值键中出现 NULL 时不会匹配。两个输入都必须是有界的。如果多行右表数据具有相同的等值键和有序值,选中哪一行是不确定的。

RIGHT OUTER JOIN

关键字 RIGHT JOIN 或 RIGHT OUTER JOIN 定义一种连接,即使左表中没有匹配行,也包含右表的所有行。当没有匹配时,连接的左侧会产生空值。

SELECT * FROM x RIGHT JOIN x AS y ON x.column_1 = y.column_2;
+----------+----------+----------+----------+
| column_1 | column_2 | column_1 | column_2 |
+----------+----------+----------+----------+
|          |          | 1        | 2        |
+----------+----------+----------+----------+

全外连接 FULL OUTER JOIN

关键字 FULL JOIN 或 FULL OUTER JOIN 定义的连接,实际上相当于 LEFT OUTER JOIN 和 RIGHT OUTER JOIN 的并集。它会显示连接左右两侧的所有行,当某一行没有匹配时,会在该行的连接列上生成空值(null)。

SELECT * FROM x FULL OUTER JOIN x AS y ON x.column_1 = y.column_2;
+----------+----------+----------+----------+
| column_1 | column_2 | column_1 | column_2 |
+----------+----------+----------+----------+
| 1        | 2        |          |          |
|          |          | 1        | 2        |
+----------+----------+----------+----------+

NATURAL JOIN

NATURAL JOIN 基于输入表之间的同名列定义内连接。如果没有找到同名列,则其行为与 CROSS JOIN 相同。

SELECT * FROM x NATURAL JOIN x AS y;
+----------+----------+
| column_1 | column_2 |
+----------+----------+
| 1        | 2        |
+----------+----------+

CROSS JOIN

CROSS JOIN(交叉连接)产生笛卡尔积,将连接左侧的每一行与连接右侧的每一行进行匹配。

SELECT * FROM x CROSS JOIN x AS y;
+----------+----------+----------+----------+
| column_1 | column_2 | column_1 | column_2 |
+----------+----------+----------+----------+
| 1        | 2        | 1        | 2        |
+----------+----------+----------+----------+

LEFT SEMI JOIN

LEFT SEMI JOIN 返回左表中在右表至少存在一条匹配行的所有行,并且只投影左表的列。

SELECT * FROM x LEFT SEMI JOIN x AS y ON x.column_1 = y.column_1;
+----------+----------+
| column_1 | column_2 |
+----------+----------+
| 1        | 2        |
+----------+----------+

RIGHT SEMI JOIN

RIGHT SEMI JOIN 返回右表中在左表里至少有一行匹配的所有行,并且只投影右表的列。

SELECT * FROM x RIGHT SEMI JOIN x AS y ON x.column_1 = y.column_1;
+----------+----------+
| column_1 | column_2 |
+----------+----------+
| 1        | 2        |
+----------+----------+

LEFT ANTI JOIN

LEFT ANTI JOIN(左反连接)返回左表中在右表里没有任何匹配行的所有行,并且只投影左表的列。

SELECT * FROM x LEFT ANTI JOIN x AS y ON x.column_1 = y.column_1;
+----------+----------+
| column_1 | column_2 |
+----------+----------+
+----------+----------+

RIGHT ANTI JOIN

RIGHT ANTI JOIN 返回右表中在左表没有任何匹配行的所有行,并且只投影右表的列。

SELECT * FROM x RIGHT ANTI JOIN x AS y ON x.column_1 = y.column_1;
+----------+----------+
| column_1 | column_2 |
+----------+----------+
+----------+----------+

LATERAL JOIN

LATERAL JOIN 允许连接的右侧引用左侧的列。从概念上说,右侧的子查询会对左侧表的每一行求值一次,这样就可以用前面表中的值来“参数化”一个子查询。

LATERAL 关键字是必需的;DataFusion 不会隐式检测 FROM 子句子查询中的关联性。

以下示例使用这些表:

CREATE TABLE departments(id INT, name TEXT) AS VALUES (1, 'HR'), (2, 'Eng'), (3, 'Sales');
CREATE TABLE employees(id INT, dept_id INT, name TEXT) AS VALUES
  (10, 1, 'Alice'), (20, 1, 'Bob'), (30, 2, 'Carol');

逗号语法

最简洁的写法是将 LATERAL 放在 FROM 子句中逗号的后面。左表中在子查询里没有匹配行的行将被排除(即内连接语义)。

SELECT d.name AS dept, e.name AS emp
FROM departments d, LATERAL (
    SELECT employees.name FROM employees WHERE employees.dept_id = d.id
) AS e
ORDER BY dept, emp;
+------+-------+
| dept | emp   |
+------+-------+
| Eng  | Carol |
| HR   | Alice |
| HR   | Bob   |
+------+-------+

CROSS JOIN LATERAL

与上面的逗号语法等价。

SELECT d.name AS dept, e.name AS emp
FROM departments d
CROSS JOIN LATERAL (
    SELECT employees.name FROM employees WHERE employees.dept_id = d.id
) AS e
ORDER BY dept, emp;
+------+-------+
| dept | emp   |
+------+-------+
| Eng  | Carol |
| HR   | Alice |
| HR   | Bob   |
+------+-------+

JOIN LATERAL … ON

带有 ON 子句的 JOIN LATERAL 会在计算完横向子查询之后,将 ON 条件作为额外的过滤条件应用。

SELECT d.name AS dept, sub.emp, sub.cnt
FROM departments d
JOIN LATERAL (
    SELECT count(*) AS cnt, min(employees.name) AS emp
    FROM employees WHERE employees.dept_id = d.id
) AS sub ON sub.cnt > 0
ORDER BY dept;
+------+-------+-----+
| dept | emp   | cnt |
+------+-------+-----+
| Eng  | Carol | 1   |
| HR   | Alice | 2   |
+------+-------+-----+

LEFT JOIN LATERAL

LEFT JOIN LATERAL 会保留左表的所有行。当 lateral 子查询没有产生匹配行时,右侧的列将填充 NULL。

SELECT d.name AS dept, e.name AS emp
FROM departments d
LEFT JOIN LATERAL (
    SELECT employees.name FROM employees WHERE employees.dept_id = d.id
) AS e ON true
ORDER BY dept, emp;
+-------+-------+
| dept  | emp   |
+-------+-------+
| Eng   | Carol |
| HR    | Alice |
| HR    | Bob   |
| Sales | NULL  |
+-------+-------+

ON 子句也可以用于过滤结果。不满足 ON 条件的行会像常规 LEFT JOIN 一样,用 NULL 进行填充后保留下来:

SELECT d.name AS dept, sub.cnt
FROM departments d
LEFT JOIN LATERAL (
    SELECT count(*) AS cnt
    FROM employees WHERE employees.dept_id = d.id
) AS sub ON sub.cnt > 0
ORDER BY dept;
+-------+------+
| dept  | cnt  |
+-------+------+
| Eng   | 1    |
| HR    | 2    |
| Sales | NULL |
+-------+------+

限制

以下模式目前尚不支持:

  • 横向子查询 SELECT 列表中的外部引用(例如 LATERAL (SELECT outer.col + 1))。
  • 横向子查询中的 HAVING。
  • FULL OUTER JOIN LATERAL、RIGHT JOIN LATERAL、RIGHT SEMI JOIN LATERAL 和 RIGHT ANTI JOIN LATERAL。

GROUP BY 子句

GROUP BY ALL
GROUP BY grouping_element [, ...]

grouping_element:
  expression
  ordinal_position
  ROLLUP(expression [, ...])
  CUBE(expression [, ...])
  GROUPING SETS ((grouping_element [, ...]) [, ...])

GROUP BY 子句在计算聚合表达式之前对行进行分组。分组元素可以是表达式、输出别名,或者是 SELECT 列表中的序号位置。

示例:

SELECT a, b, MAX(c) FROM table_name GROUP BY a, b;
SELECT a AS key, COUNT(*) FROM table_name GROUP BY key;
SELECT a, b, COUNT(*) FROM table_name GROUP BY 1, 2;

GROUP BY ALL 按 SELECT 列表中的所有非聚合表达式进行分组。

SELECT a, b, SUM(c) FROM table_name GROUP BY ALL;

分组集(grouping sets)允许单个查询计算多个分组级别的聚合结果。ROLLUP(a, b) 先按 (a, b) 分组计算聚合行,再按 a 分组计算,最后对所有输入行汇总。CUBE(a, b) 会计算 a 和 b 所有组合的聚合行。GROUPING SETS 可以让你显式列出各个分组级别。

SELECT a, b, SUM(c) FROM table_name GROUP BY ROLLUP(a, b);
SELECT a, b, SUM(c) FROM table_name GROUP BY CUBE(a, b);
SELECT a, b, SUM(c)
FROM table_name
GROUP BY GROUPING SETS ((a), (a, b), ());

某些聚合函数接受一个可选的排序要求,例如 ARRAY_AGG。如果给出了排序要求,聚合将按该顺序计算。

SELECT a, b, ARRAY_AGG(c ORDER BY d) FROM table_name GROUP BY a, b;

HAVING 子句

HAVING condition

HAVING 子句在聚合之后对分组进行过滤。它可以引用分组表达式、聚合表达式,以及 SELECT 列表中的别名。

SELECT a, b, MAX(c) AS max_c
FROM table_name
GROUP BY a, b
HAVING max_c > 10;

WINDOW 子句

WINDOW window_name AS (window_definition) [, ...]

WINDOW 子句定义了具名窗口规范,窗口函数可以引用这些规范。完整的窗口函数参考请参见窗口函数。

SELECT
  depname,
  empno,
  salary,
  AVG(salary) OVER w AS avg_salary
FROM empsalary
WINDOW w AS (PARTITION BY depname ORDER BY salary DESC);

QUALIFY 子句

QUALIFY condition

QUALIFY 子句在窗口函数求值之后对行进行过滤。包含 QUALIFY 的查询必须在 SELECT 列表或 QUALIFY 表达式中包含窗口函数。QUALIFY 可以引用 SELECT 列表中的别名。

SELECT ROW_NUMBER() OVER (PARTITION BY region ORDER BY sales DESC) AS rk
FROM table_name
QUALIFY rk <= 3;

集合运算

query UNION [ALL | DISTINCT] [BY NAME] query
query INTERSECT [ALL | DISTINCT] query
query EXCEPT [ALL | DISTINCT] query

集合操作将两个查询的结果合并为一个结果集。它们作用于整行而非单个列,并且参与运算的查询必须产生兼容的列。除 UNION ... BY NAME 变体外,各输入的输出列数必须相同。

UNION 返回两个输入中的所有行,并默认去除重复行;UNION DISTINCT 与 UNION 等价;UNION ALL 则保留重复行。

示例:

SELECT
    a,
    b,
    c
FROM table1
UNION ALL
SELECT
    a,
    b,
    c
FROM table2

INTERSECT 返回在两个输入中都出现的行。EXCEPT 返回左输入中存在而右输入中不存在的行。两者都支持 ALL 和 DISTINCT。

SELECT a FROM table1
INTERSECT
SELECT a FROM table2;

SELECT a FROM table1
EXCEPT ALL
SELECT a FROM table2;

UNION BY NAME 按列名而非按位置匹配列。UNION ALL BY NAME 保留重复项,UNION DISTINCT BY NAME 去除重复项。

SELECT a, b FROM table1
UNION BY NAME
SELECT b, a FROM table2;

集合运算之后可以跟 ORDER BY、LIMIT 和 OFFSET 子句,它们作用于合并后的结果。

ORDER BY 子句

ORDER BY order_expression [ASC | DESC] [NULLS FIRST | NULLS LAST] [, ...]

ORDER BY 对查询结果进行排序。每个 order_expression 可以是一个表达式、一个 SELECT 别名,或一个序号位置。默认排序方向为升序(ASC)。

如果多行在所有 ORDER BY 表达式上的取值都相同,则它们之间的相对顺序是未定义的。当确切的行顺序很重要时,请添加额外的 ORDER BY 表达式来打破并列。

示例:

SELECT age, person FROM table_name ORDER BY age;
SELECT age, person FROM table_name ORDER BY age DESC;
SELECT age AS years, person FROM table_name ORDER BY years;
SELECT age, person FROM table_name ORDER BY 1, person DESC;

使用 NULLS FIRST 或 NULLS LAST 控制空值的排序位置:

SELECT age, person FROM table_name ORDER BY age DESC NULLS LAST;

使用 DuckDB 方言时,DataFusion 支持 ORDER BY ALL,它会按照 SELECT 列表中的所有列从左到右依次排序。所有选中的项都必须是列引用,不支持按 a + b 这类计算表达式排序:

SET datafusion.sql_parser.dialect = 'DuckDB';
SELECT address, zip FROM addresses ORDER BY ALL DESC;

LIMIT 和 OFFSET 子句

[LIMIT count]
[OFFSET count]

LIMIT 用于限制返回的行数。OFFSET 用于在返回结果之前跳过若干行。计数表达式必须是常量表达式,其求值结果为非负整数或 NULL;不允许使用列引用。NULL 不产生任何影响。

在没有 ORDER BY 子句的情况下,LIMIT 和 OFFSET 作用于未指定的行顺序,因此返回的行不保证具有确定性。

示例:

SELECT age, person FROM table_name LIMIT 10;
SELECT age, person FROM table_name OFFSET 20;
SELECT age, person FROM table_name LIMIT 10 OFFSET 20;
SELECT age, person FROM table_name OFFSET 20 LIMIT 10;

DataFusion 同样支持 MySQL 风格的 LIMIT offset, count 写法:

SELECT age, person FROM table_name LIMIT 20, 10;

管道操作符

query |> pipe_operator [|> pipe_operator ...]

DataFusion 支持 BigQuery 风格的管道操作符(|>)。

DataFusion 目前支持以下管道操作符:

WHERE

select * from range(0,10)
|> where value < 2;
+-------+
| value |
+-------+
| 0     |
| 1     |
+-------+

ORDER BY

select * from range(0,3)
|> order by value desc;
+-------+
| value |
+-------+
| 2     |
| 1     |
| 0     |
+-------+

LIMIT

select * from range(0,3)
|> order by value desc
|> limit 1;
+-------+
| value |
+-------+
| 2     |
+-------+

SELECT

select * from range(0,3)
|> select value + 10;
+---------------------------+
| range().value + Int64(10) |
+---------------------------+
| 10                        |
| 11                        |
| 12                        |
+---------------------------+

EXTEND

select * from range(0,3)
|> extend -value AS minus_value;
+-------+-------------+
| value | minus_value |
+-------+-------------+
| 0     | 0           |
| 1     | -1          |
| 2     | -2          |
+-------+-------------+

AS

select * from range(0,3)
|> as my_range
|> SELECT my_range.value;
+-------+
| value |
+-------+
| 0     |
| 1     |
| 2     |
+-------+

UNION

select * from range(0,3)
|> union all (
  select * from range(3,6)
);
+-------+
| value |
+-------+
| 0     |
| 1     |
| 2     |
| 3     |
| 4     |
| 5     |
+-------+

INTERSECT

select * from range(0,100)
|> INTERSECT DISTINCT (
  select 3
);
+-------+
| value |
+-------+
| 3     |
+-------+

EXCEPT

select * from range(0,10)
|> EXCEPT DISTINCT (select * from range(5,10));
+-------+
| value |
+-------+
| 0     |
| 1     |
| 2     |
| 3     |
| 4     |
+-------+

AGGREGATE 聚合

select * from range(0,3)
|> aggregate sum(value) AS total;
+-------+
| total |
+-------+
| 3     |
+-------+

JOIN

(
  SELECT 'apples' AS item, 2 AS sales
  UNION ALL
  SELECT 'bananas' AS item, 5 AS sales
)
|> AS produce_sales
|> LEFT JOIN
     (
       SELECT 'apples' AS item, 123 AS id
     ) AS produce_data
   ON produce_sales.item = produce_data.item
|> SELECT produce_sales.item, sales, id;
+--------+-------+------+
| item   | sales | id   |
+--------+-------+------+
| apples | 2     | 123  |
| bananas| 5     | NULL |
+--------+-------+------+

评论

登录后参与评论

正在加载评论…