12 KiB
12 KiB
Apache Doris SQL 语法参考
数据类型
| 类型 | 说明 | 示例 |
|---|---|---|
| BOOLEAN | 布尔 | active BOOLEAN |
| TINYINT | 1字节整数 | level TINYINT |
| SMALLINT | 2字节整数 | age SMALLINT |
| INT | 4字节整数 | count INT |
| BIGINT | 8字节整数 | id BIGINT |
| LARGEINT | 16字节整数 | hash_key LARGEINT |
| FLOAT | 4字节浮点 | score FLOAT |
| DOUBLE | 8字节浮点 | price DOUBLE |
| DECIMAL(p,s) | 定点数 | amount DECIMAL(18,2) |
| DATE | 日期 | birth_date DATE |
| DATETIME | 日期时间(精确到秒) | created_at DATETIME |
| CHAR(n) | 定长字符串 | code CHAR(10) |
| VARCHAR(n) | 变长字符串 | name VARCHAR(100) |
| STRING | 变长字符串(无长度限制) | description STRING |
| BITMAP | 位图(精确去重) | user_bitmap BITMAP |
| HLL | HyperLogLog(近似去重) | user_hll HLL |
| JSON | JSON 数据 | props JSON |
| ARRAY<type> | 数组 | tags ARRAY<STRING> |
| MAP<k,v> | 映射 | props MAP<STRING,STRING> |
| STRUCT<field:type,...> | 结构体 | info STRUCT<id:INT,name:STRING> |
时间函数
-- 当前时间
NOW() -- 当前日期时间
CURDATE() -- 当前日期
CURRENT_TIMESTAMP() -- 当前时间戳
-- 格式转换
DATE_FORMAT(date_col, '%Y-%m-%d') -- 日期格式化
DATE_FORMAT(datetime_col, '%Y-%m-%d %H:%i:%s') -- 时间格式化
STR_TO_DATE(str, '%Y-%m-%d') -- 字符串转日期
-- 日期计算
DATE_ADD(date_col, INTERVAL 7 DAY) -- 加7天
DATE_SUB(date_col, INTERVAL 7 DAY) -- 减7天
DATEDIFF(end_date, start_date) -- 日期差(天数)
TIMESTAMPDIFF(unit, start, end) -- 时间差(指定单位)
TIMESTAMPADD(unit, interval, datetime) -- 时间加
-- 日期提取
YEAR(date_col) -- 年
MONTH(date_col) -- 月
DAY(date_col) -- 日
HOUR(datetime_col) -- 时
MINUTE(datetime_col) -- 分
SECOND(datetime_col) -- 秒
QUARTER(date_col) -- 季度 (1-4)
WEEK(date_col) -- 年中第几周
DAYOFWEEK(date_col) -- 周几 (1=周日)
DAYOFYEAR(date_col) -- 年中第几天
-- Unix 时间戳
UNIX_TIMESTAMP() -- 当前 Unix 时间戳
UNIX_TIMESTAMP(datetime_col) -- 转换为 Unix 时间戳
FROM_UNIXTIME(timestamp) -- Unix 时间戳转时间字符串
FROM_UNIXTIME(timestamp, fmt) -- 带格式的转换
-- Doris 日期格式符(不同于 Spark)
-- %Y: 4位年, %m: 2位月, %d: 2位日
-- %H: 24小时制, %i: 分钟, %s: 秒
-- %j: 年中天数, %W: 周名
字符串函数
-- 常用函数
CONCAT(str1, str2, ...) -- 字符串拼接
CONCAT_WS('-', str1, str2, ...) -- 用分隔符拼接
LOWER(str) -- 转小写
UPPER(str) -- 转大写
TRIM(str) -- 去两端空格
LTRIM(str) -- 去左空格
RTRIM(str) -- 去右空格
LENGTH(str) -- 字符串长度
CHAR_LENGTH(str) -- 字符数(中文友好)
SUBSTRING(str, pos, len) -- 截取字符串(pos从1开始)
LEFT(str, len) -- 取左边len个字符
RIGHT(str, len) -- 取右边len个字符
REVERSE(str) -- 反转字符串
REPEAT(str, n) -- 重复n次
SPACE(n) -- 生成n个空格
-- 查找与替换
INSTR(str, substr) -- 查找子串位置
LOCATE(substr, str, pos) -- 从pos位置查找
REPLACE(str, old, new) -- 替换
REGEXP_EXTRACT(str, pattern, idx) -- 正则提取(注意和 Spark 参数不同)
REGEXP_REPLACE(str, pattern, replacement) -- 正则替换
-- 分割
SPLIT_BY_STRING(str, delimiter) -- 分割(Doris 特有)
SPLIT_PART(str, delimiter, idx) -- 取分割后的第idx部分
-- 其他
INITCAP(str) -- 首字母大写
LPAD(str, len, pad) -- 左填充
RPAD(str, len, pad) -- 右填充
HEX(str) -- 转16进制
UNHEX(str) -- 16进制转字符串
聚合函数
-- 基础聚合
COUNT(*) -- 计数(含NULL行)
COUNT(col) -- 计数(不含NULL)
COUNT(DISTINCT col) -- 去重计数
SUM(col) -- 求和
AVG(col) -- 平均值
MIN(col) -- 最小值
MAX(col) -- 最大值
-- 集合聚合
GROUP_CONCAT(col SEPARATOR ',') -- 字符串聚合(类似 collect_list)
APPROX_COUNT_DISTINCT(col) -- 近似去重计数
-- 统计函数
VARIANCE(col) -- 方差
VAR_POP(col) -- 总体方差
VAR_SAMP(col) -- 样本方差
STDDEV(col) -- 标准差
STDDEV_POP(col) -- 总体标准差
STDDEV_SAMP(col) -- 样本标准差
-- Bitmap 精确去重(Doris 特有)
-- 用于 Aggregate Key 模型中定义为 BITMAP 的列
-- bitmap_union_count(bitmap_col) -- 精确去重计数
-- bitmap_union(bitmap_col) -- 合并 bitmap
-- bitmap_hash(col) -- 将值转为 bitmap(用于写入)
-- HLL 近似去重(Doris 特有)
-- hll_union_agg(hll_col) -- 近似去重计数
-- hll_cardinality(hll_col) -- 返回 HLL 基数
-- hll_hash(col) -- 将值转为 HLL(用于写入)
条件表达式
-- CASE WHEN
CASE
WHEN condition1 THEN result1
WHEN condition2 THEN result2
ELSE default_result
END
-- CASE 字段匹配
CASE field
WHEN value1 THEN result1
WHEN value2 THEN result2
ELSE default_result
END
-- COALESCE(取第一个非空值)
COALESCE(col1, col2, default_value)
-- NULLIF(相等返回NULL)
NULLIF(col1, col2)
-- IF(简单条件)
IF(condition, true_value, false_value)
-- IFNULL(空值替换,等同 NVL)
IFNULL(col, default_value)
JSON 函数
-- 解析与提取
JSON_PARSE(json_str) -- 解析 JSON 字符串
JSON_EXTRACT(json_str, '$.field') -- 提取 JSON 字段(返回 JSON 类型)
JSON_EXTRACT_STRING(json_str, '$.field') -- 提取 JSON 字段(返回 STRING)
JSON_EXTRACT_INT(json_str, '$.field') -- 提取 JSON 字段(返回 INT)
JSON_EXTRACT_DOUBLE(json_str, '$.field') -- 提取 JSON 字段(返回 DOUBLE)
JSON_EXTRACT_BOOL(json_str, '$.field') -- 提取 JSON 字段(返回 BOOLEAN)
-- 路径语法
-- $ : 根节点
-- $.field : 对象字段
-- $[0] : 数组索引
-- $.a.b : 嵌套字段
-- 构造
JSON_OBJECT('key1', val1, 'key2', val2) -- 构造 JSON 对象
JSON_ARRAY(val1, val2, ...) -- 构造 JSON 数组
-- 查询
JSON_LENGTH(json_str) -- JSON 长度
JSON_KEYS(json_str) -- JSON 所有 key
JSON_VALID(json_str) -- 是否合法 JSON
ARRAY 函数
-- 创建
ARRAY(val1, val2, ...) -- 创建数组
-- 访问
array_contains(arr, val) -- 判断是否包含
element_at(arr, idx) -- 取元素(idx从1开始)
arr[idx] -- 取元素(idx从0开始)
-- 操作
SIZE(arr) -- 数组长度
ARRAY_JOIN(arr, delimiter) -- 数组转字符串
CONCAT(arr1, arr2) -- 数组拼接
-- 展开与排序
EXPLODE(arr) -- 展开数组为多行(LATERAL VIEW 中使用)
ARRAY_SORT(arr) -- 排序
ARRAY_DISTINCT(arr) -- 去重
与 Spark SQL 的主要差异
| 特性 | Spark SQL | Apache Doris | 说明 |
|---|---|---|---|
| 日期格式符 | yyyy-MM-dd |
%Y-%m-%d |
Doris 用 MySQL 风格格式符 |
| 当前时间 | current_timestamp() |
NOW() 或 CURRENT_TIMESTAMP() |
都支持,Doris 偏好 NOW() |
| 日期加减 | date_add(col, 7) |
DATE_ADD(col, INTERVAL 7 DAY) |
Doris 需要 INTERVAL 语法 |
| 正则提取 | regexp_extract(str, pattern, idx) |
REGEXP_EXTRACT(str, pattern, idx) |
参数名可能不同 |
| LEFT SEMI JOIN | ✅ 支持 | ❌ 不支持 | 用 IN 子查询替代 |
| LEFT ANTI JOIN | ✅ 支持 | ❌ 不支持 | 用 NOT IN / NOT EXISTS 替代 |
| INSERT OVERWRITE | ✅ 支持 | ✅ 2.0+ 支持 | 早期版本不支持 |
| CTE (WITH) | ✅ 支持 | ✅ 支持 | 都支持 |
| MERGE INTO | ✅ 支持 | ❌ 不支持 | Doris 用 UPSERT 替代 |
| 临时表链式处理 | ✅ 推荐 | ✅ 统一规范 | 编码规范层面统一禁止 CTE |
| 精确去重 | COUNT(DISTINCT) | COUNT(DISTINCT) 或 BITMAP | Doris BITMAP 性能更好 |
| 近似去重 | approx_count_distinct |
HLL 类型 | Doris 内置 HLL 类型 |
| UPDATE/DELETE | ❌ 不支持 | ✅ 支持 | Doris 支持 DML |
| UPSERT | ❌ 不支持 | ❌ 不直接支持 | 用 Aggregate/Unique Key 模型替代 |
| 分页 | LIMIT(无OFFSET) | LIMIT + OFFSET | Doris 完整支持 |
| JSON | get_json_object |
JSON_EXTRACT_STRING 等系列函数 |
函数名完全不同 |
| collect_list/set | ✅ 支持 | ❌ 不直接支持 | 用 GROUP_CONCAT 替代 |
| LATERAL VIEW explode | ✅ 支持 | ✅ 支持 | 语法兼容 |
SQL 生成规则
通用规则(所有引擎统一)
- 禁止使用 CTE (WITH 子句),每个主要逻辑步骤必须物化为临时表
- 先 DROP 再 CREATE:
DROP TABLE IF EXISTS ...; CREATE TABLE ... AS SELECT ...; - 禁止
SELECT *,必须明确列出所有字段 - 多表查询时所有表必须使用简短别名
- 每个步骤前添加注释说明
- 谓词下推:过滤条件前置,JOIN 时在 WHERE 中一并添加过滤
- 临时表命名:
${db_tmp_env}.tmp_{业务简称}_{步骤序号}
Doris 特有规则
- 使用
INSERT INTO写入目标表(Doris 2.0+ 也支持INSERT OVERWRITE) - Aggregate Key 表自动合并相同 Key 的数据
- Unique Key 表自动按主键去重,保留最新数据
- 不支持
LEFT SEMI JOIN/LEFT ANTI JOIN,用IN/NOT IN替代 - 精确去重推荐
BITMAP,近似去重推荐HLL - 日期函数用 MySQL 风格:
DATE_FORMAT(col, '%Y-%m-%d')(不是yyyy-MM-dd)DATE_ADD(col, INTERVAL 7 DAY)(不是date_add(col, 7))CURDATE()/NOW()
- 不支持
collect_list/collect_set,用GROUP_CONCAT替代 - 时间范围筛选:
-- 日账期过滤 WHERE stat_date = '${day_id}' -- 最近N个月 WHERE stat_date >= DATE_FORMAT(DATE_SUB(STR_TO_DATE('${month_id}', '%Y%m'), INTERVAL N MONTH), '%Y%m') AND stat_date < '${month_id}'
SQL 脚本结构
-- =====================================================================
-- @SqlName: doris-D-SQL-{表名}
-- @Engine: doris
-- ...(头注释)
-- =====================================================================
-- Step01: {步骤描述}
DROP TABLE IF EXISTS ${db_tmp_env}.tmp_xxx_01;
CREATE TABLE ${db_tmp_env}.tmp_xxx_01 AS
SELECT ...;
-- Step02: {步骤描述}
DROP TABLE IF EXISTS ${db_tmp_env}.tmp_xxx_02;
CREATE TABLE ${db_tmp_env}.tmp_xxx_02 AS
SELECT ...;
-- 最后一步:写入目标表
INSERT INTO ${db_eda_env}.target_table
SELECT ...;