Select
功能描述
SELECT语句用于从表中查询数据,是Spark SQL中最基本的查询语句。Spark 4.0支持完整的SELECT语法,包括LATERAL、PIVOT/UNPIVOT、OFFSET分页等特性。
语法格式
[ WITH with_query [, ...] ]
SELECT [ ALL | DISTINCT ] { * | projectItem [, ...] }
FROM table_reference [, ...]
[ WHERE boolean_expression ]
[ GROUP BY { expression | GROUPING SETS ( ... ) | ROLLUP ( ... ) | CUBE ( ... ) } [, ...] ]
[ HAVING boolean_expression ]
[ PIVOT ( aggregate_expr FOR pivot_column IN ( value1 [, ...] ) ) ]
[ UNPIVOT ( value_column FOR name_column IN ( column1 [, ...] ) ) ]
[ LATERAL VIEW function_expr AS alias [, ...] ]
[ LATERAL ( subquery ) ]
[ ORDER BY { expression [ ASC | DESC ] [ NULLS { FIRST | LAST } ] } [, ...] ]
[ SORT BY { expression [ ASC | DESC ] [ NULLS { FIRST | LAST } ] } [, ...] ]
[ CLUSTER BY expression [, ...] ]
[ DISTRIBUTE BY expression [, ...] ]
[ OFFSET integer_expression ]
[ LIMIT integer_expression ] 其中 projectItem 为:
expression [ [ AS ] alias ]
table_reference 为:
{ table_name [ TABLE ] [ alias ]
| join_table | LATERAL ( subquery ) [ alias ]
| ( subquery ) [ alias ]
| VALUES ( { expression } [, ...] ) [, ...] [ alias ]
| UNNEST(expression) [ alias ] } 参数说明
| 参数 | 说明 |
|---|---|
| WITH with_query | 定义公共表表达式(CTE),用于简化复杂查询,提高可读性。详见WITH...AS。 |
| ALL | 返回所有行,包括重复行。为默认选项。 |
| DISTINCT | 从结果集中移除重复的行。 |
| * | 查询所有列。 |
| projectItem | 指定查询的列或表达式,可使用AS指定别名。 |
| FROM table_reference | 指定查询的数据源,可以是表名、子查询、JOIN结果、LATERAL子查询等。详见FROM。 |
| WHERE | 指定过滤条件,仅返回满足条件的行。详见WHERE。 |
| GROUP BY | 按指定表达式分组,通常与聚合函数配合使用。支持GROUPING SETS、ROLLUP、CUBE扩展。 |
| HAVING | 对GROUP BY的结果进行过滤。详见HAVING。 |
| PIVOT | 行转列操作,根据指定列的值将行数据旋转为列。 |
| UNPIVOT | 列转行操作,将列数据旋转为行。 |
| LATERAL VIEW | 与表生成函数(如explode)配合使用,将函数输出展开为多行。 |
| LATERAL (subquery) | LATERAL子查询,允许子查询引用外部查询的列。 |
| ORDER BY | 全局排序。详见ORDER BY。 |
| SORT BY | 局部排序,每个Reducer内排序。详见SORT BY。 |
| CLUSTER BY | 分桶并桶内排序,等效于DISTRIBUTE BY + SORT BY同字段。详见CLUSTER BY。 |
| DISTRIBUTE BY | 按指定字段分桶,将相同键值的数据分配到同一Reducer。详见DISTRIBUTE BY。 |
| OFFSET | 跳过前N行结果,用于分页查询。 |
| LIMIT | 限制返回的行数。 |
| NULLS FIRST / NULLS LAST | 指定NULL值在排序结果中的位置。NULLS FIRST将NULL排在最前,NULLS LAST将NULL排在最后。 |
注意事项
- 所查询的表必须是已经存在的表,否则提示查询错误。
- 在WHERE子句中使用NOT IN时,必须保证子查询结果集不包含任何NULL值。一旦存在NULL,整个查询结果将为空集。详见下方常见问题。
示例
- 基本查询:
SELECT * FROM student;
- 带DISTINCT去重:
SELECT DISTINCT name FROM student;
- 带WHERE条件:
SELECT name, score FROM student WHERE score > 90;
- 带GROUP BY和HAVING:
SELECT class_id, AVG(score) AS avg_score FROM student GROUP BY class_id HAVING AVG(score) > 80;
- 带OFFSET分页(Spark 4.0):
SELECT * FROM student ORDER BY score DESC LIMIT 10 OFFSET 20;
- 带PIVOT行转列(Spark 4.0):
SELECT * FROM sales PIVOT (SUM(amount) FOR year IN (2023, 2024, 2025));
- 带LATERAL子查询(Spark 4.0):
SELECT * FROM orders, LATERAL (SELECT * FROM items WHERE items.order_id = orders.id);
:: 类型转换
SELECT '123' :: INT;
-- 等价于 CAST('123' AS INT) COLLATE 排序规则
SELECT name FROM t ORDER BY name COLLATE unicode_ci;
常见问题:NOT IN子查询中有NULL值,查询结果为空怎么办?
- 问题概述:SQL语法中只要NOT IN子查询中有一个NULL值,整个查询结果就会是空集(无数据返回)。
- 示例:如下示例中期望的结果是3,但是反馈的是空集。
-- 表A -- 表B id value --- ----- 1 1 2 2 3
执行以下SQL语句:
SELECT * FROM A WHERE id NOT IN (SELECT value FROM B);
- 原因分析:
id NOT IN (1, 2, NULL) 等价于 id <> 1 AND id <> 2 AND id <> NULL
id <> NULL 的结果是UNKNOWN(SQL的三值逻辑),整个表达式为FALSE,因此无数据返回。
- 解决方案:
方案1:用NOT EXISTS替代NOT IN
SELECT * FROM A WHERE NOT EXISTS ( SELECT 1 FROM B WHERE B.value = A.id );
方案2:在子查询中过滤掉NULL
SELECT * FROM A WHERE id NOT IN ( SELECT value FROM B WHERE value IS NOT NULL );