Files
smart-data-dev-skill/one-skill/smart-data-developer/references/sql/reference/doris-sql-syntax.md
2026-05-13 11:03:00 +08:00

321 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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\> |
---
## 时间函数
```sql
-- 当前时间
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: 周名
```
---
## 字符串函数
```sql
-- 常用函数
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进制转字符串
```
---
## 聚合函数
```sql
-- 基础聚合
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用于写入
```
---
## 条件表达式
```sql
-- 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 函数
```sql
-- 解析与提取
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 函数
```sql
-- 创建
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 生成规则
### 通用规则(所有引擎统一)
1. **禁止使用 CTE (WITH 子句)**,每个主要逻辑步骤必须物化为临时表
2. **先 DROP 再 CREATE**`DROP TABLE IF EXISTS ...; CREATE TABLE ... AS SELECT ...;`
3. **禁止 `SELECT *`**,必须明确列出所有字段
4. 多表查询时所有表必须使用简短别名
5. 每个步骤前添加注释说明
6. **谓词下推**过滤条件前置JOIN 时在 WHERE 中一并添加过滤
7. 临时表命名:`${db_tmp_env}.tmp_{业务简称}_{步骤序号}`
### Doris 特有规则
1. 使用 `INSERT INTO` 写入目标表Doris 2.0+ 也支持 `INSERT OVERWRITE`
2. Aggregate Key 表自动合并相同 Key 的数据
3. Unique Key 表自动按主键去重,保留最新数据
4. 不支持 `LEFT SEMI JOIN` / `LEFT ANTI JOIN`,用 `IN` / `NOT IN` 替代
5. 精确去重推荐 `BITMAP`,近似去重推荐 `HLL`
6. 日期函数用 MySQL 风格:
- `DATE_FORMAT(col, '%Y-%m-%d')`(不是 `yyyy-MM-dd`
- `DATE_ADD(col, INTERVAL 7 DAY)`(不是 `date_add(col, 7)`
- `CURDATE()` / `NOW()`
7. 不支持 `collect_list` / `collect_set`,用 `GROUP_CONCAT` 替代
8. 时间范围筛选:
```sql
-- 日账期过滤
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 脚本结构
```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 ...;
```