更新时间:2026-07-03 GMT+08:00
分享

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 ] }

参数说明

表1 参数说明

参数

说明

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
    );

相关文档