当前位置: 首页 > news >正文

【Elasticsearch从入门到精通】第40篇:Elasticsearch SQL语法详解——从DDL到复杂查询

上一篇【第39篇】Elasticsearch SQL接口——用熟悉的SQL语法查询ES
下一篇【第41篇】为什么需要搜索引擎——关系数据库的搜索困境(明日更新,敬请期待)


摘要

在上一篇中我们了解了ES SQL接口的基本用法,本文将深入讲解ES SQL的完整语法体系。从词法结构(标识符、常量、运算符)入手,逐步展开SQL命令的详细语法,包括SHOW TABLES查看可用索引、SHOW COLUMNS和DESCRIBE查看字段结构、SELECT基本查询的完整流程。随后,我们将系统介绍ES SQL支持的函数体系——聚合函数(AVG/COUNT/MAX/MIN/SUM等)、数学函数(ABS/CEIL/FLOOR/ROUND)、字符串函数(CONCAT/SUBSTRING/LTRIM等)、日期函数(CURDATE/NOW/YEAR/MONTH等),并通过实战示例展示GROUP BY/HAVING/ORDER BY/LIMIT等子句的组合使用。最后,我们将总结ES SQL的已知限制,并介绍SQL CLI工具的使用方法。

一、词法结构

1.1 关键字

ES SQL中的关键字(Keyword)具有固定含义,不区分大小写

-- 以下写法等价SELECT*FROMlibrary;select*fromlibrary;SeLeCt*FrOmlibrary;

常用的SQL关键字包括:SELECTFROMWHEREGROUP BYHAVINGORDER BYLIMITANDORNOTINBETWEENLIKEIS NULLIS NOT NULLASDESCASCJOINON等。

最佳实践:关键字全部大写,标识符使用小写,提高代码可读性。

1.2 标识符

标识符用于标识表名(索引名)和列名(字段名),分为带引号和不带引号两种:

-- 不带引号的标识符(不与关键字冲突时可用)SELECTip_addressFROMhosts;-- 带双引号的标识符(包含特殊字符或与关键字冲突时必须使用)SELECTip_addressFROM"hosts-*";SELECT"from"FROM"<logstash-{now/d}>";

标识符使用双引号,字符串常量使用单引号,两者不可互换:

-- 正确SELECT"first_name"FROMmusiciansWHERElast_name='Chen';-- 错误:不能用单引号引用列名-- SELECT 'first_name' FROM musicians;

1.3 直接常量

字符串常量

字符串用单引号包裹,转义使用两个单引号:

SELECT'Hello World';SELECT'Captain EO''s Voyage';-- 包含单引号的字符串
数值常量

支持十进制和科学记数法:

SELECT1969;SELECT3.14;SELECT.1234;SELECT4E5;SELECT1.2e-3;

类型推断规则:包含小数点的为Double类型,否则优先判断为Integer,超出范围则为Long

1.4 注释

ES SQL支持两种注释风格:

-- 单行注释:查询所有书籍SELECT*FROMlibrary;/* 多行注释: 这是第一行注释 这是第二行注释 */SELECTnameFROMlibraryWHEREpage_count>500;

二、SQL命令详解

2.1 SHOW TABLES:查看可用索引

SHOW TABLES命令列出当前用户可访问的索引(表):

SHOWTABLES;

使用多索引模式(通配符匹配):

-- 查看所有以emp开头的索引SHOWTABLESLIKE'emp%';-- 查看所有索引,排除以logstash-开头的SHOWTABLES"*,-logstash-*";

多索引模式和LIKE模式的区别:

特性多索引模式LIKE模式
引号双引号单引号
通配符*匹配任意字符%匹配任意字符序列
排除支持支持(-前缀)不支持
示例"*,-l*"'emp%'
转义不需要ESCAPE子句

2.2 SHOW COLUMNS:查看列信息

SHOWCOLUMNSFROMlibrary;

返回结果包含列名、数据类型、是否可为空等信息。

2.3 DESCRIBE:查看表结构

DESCRIBE(可缩写为DESC)用于查看索引的结构信息:

-- 两种写法等价DESCRIBElibrary;DESClibrary;

2.4 SELECT基本语法

SELECT是ES SQL中最核心、功能最丰富的命令:

SELECTselect_expr[,...]FROMtable_name[WHEREcondition][GROUPBYgrouping_element[,...]][HAVINGcondition][ORDERBYexpression[ASC|DESC][,...]][LIMIT{count|ALL}]

SELECT的执行流程:

  1. FROM:确定查询的数据源(索引)
  2. WHERE:过滤不满足条件的行
  3. GROUP BY:将结果按分组元素分组
  4. HAVING:过滤不满足条件的组
  5. SELECT:计算输出表达式
  6. ORDER BY:对结果排序
  7. LIMIT:限制返回的行数
SELECT列表
-- 查询指定列SELECTname,authorFROMlibrary;-- 使用AS指定列别名SELECTnameASbook_name,page_countASpagesFROMlibrary;-- 使用*查询所有列SELECT*FROMlibrary;-- 使用表达式SELECTname,page_count*0.1ASprice_estimateFROMlibrary;
FROM子句
-- 指定索引名FROMlibrary;-- 使用别名FROMlibraryASlib;FROMlibrary lib;-- 通配符匹配多个索引FROM"logs-*";-- 特殊模式FROM"<logstash-{now/d}>";
WHERE子句

WHERE子句用于行级过滤:

-- 等值查询SELECT*FROMlibraryWHEREauthor='Frank Herbert';-- 范围查询SELECT*FROMlibraryWHEREpage_countBETWEEN400AND600;-- IN查询SELECT*FROMlibraryWHEREauthorIN('Frank Herbert','Dan Simmons');-- LIKE模糊查询SELECT*FROMlibraryWHEREnameLIKE'%eow%';-- IS NULL / IS NOT NULLSELECT*FROMlibraryWHERErelease_dateISNOTNULL;-- 组合条件SELECT*FROMlibraryWHEREpage_count>500ANDauthor='Frank Herbert';
GROUP BY子句

GROUP BY将结果按指定列分组,通常配合聚合函数使用:

-- 按作者分组,统计每人书籍数量和平均页数SELECTauthor,COUNT(*)ASbook_count,AVG(page_count)ASavg_pages,MAX(page_count)ASmax_pages,MIN(page_count)ASmin_pagesFROMlibraryGROUPBYauthor;
HAVING子句

HAVING子句对GROUP BY产生的组进行过滤:

-- 查找平均页数超过500的作者SELECTauthor,AVG(page_count)ASavg_pagesFROMlibraryGROUPBYauthorHAVINGAVG(page_count)>500;

WHERE vs HAVING:WHERE在分组前过滤行(处理单行),HAVING在分组后过滤组(处理组)。WHERE不能使用聚合函数,HAVING可以。

ORDER BY子句

ORDER BY对结果进行排序:

-- 按页数升序SELECT*FROMlibraryORDERBYpage_countASC;-- 按页数降序SELECT*FROMlibraryORDERBYpage_countDESC;-- 多字段排序SELECT*FROMlibraryORDERBYauthorASC,page_countDESC;-- 按列位置排序SELECTname,author,page_countFROMlibraryORDERBY3DESC;-- 按_score排序(ES特有)SELECT*FROMlibraryORDERBYSCORE()DESC;
LIMIT子句
-- 返回前5条SELECT*FROMlibraryLIMIT5;-- 返回所有结果SELECT*FROMlibraryLIMITALL;

警告:使用LIMIT ALL时,如果数据量很大,可能导致内存溢出。建议使用Cursor分页替代。

三、函数体系

3.1 聚合函数

聚合函数对一组值进行计算,返回单一值。通常与GROUP BY配合使用。

函数说明示例
AVG(expr)平均值AVG(page_count)
COUNT(*)计数(含NULL)COUNT(*)
COUNT(expr)非NULL值计数COUNT(author)
MAX(expr)最大值MAX(page_count)
MIN(expr)最小值MIN(page_count)
SUM(expr)求和SUM(page_count)
KURTOSIS(expr)峰度KURTOSIS(page_count)
SKEWNESS(expr)偏度SKEWNESS(page_count)
FIRST(expr)第一个值FIRST(name)
LAST(expr)最后一个值LAST(name)
VAR_POP(expr)总体方差VAR_POP(score)
VAR_SAMP(expr)样本方差VAR_SAMP(score)
STDDEV_POP(expr)总体标准差STDDEV_POP(score)
STDDEV_SAMP(expr)样本标准差STDDEV_SAMP(score)

综合聚合查询示例:

SELECTauthor,COUNT(*)AStotal_books,SUM(page_count)AStotal_pages,AVG(page_count)ASavg_pages,MIN(page_count)ASshortest,MAX(page_count)ASlongest,STDDEV_POP(page_count)ASpage_stddevFROMlibraryGROUPBYauthorORDERBYtotal_booksDESC;

3.2 数学函数

函数说明示例结果
ABS(x)绝对值ABS(-5)5
CEIL(x)向上取整CEIL(4.3)5
FLOOR(x)向下取整FLOOR(4.7)4
ROUND(x)四舍五入ROUND(4.56)5
ROUND(x, n)保留n位小数ROUND(4.567, 2)4.57
SQRT(x)平方根SQRT(16)4.0
EXP(x)e的x次方EXP(1)2.718…
LN(x)自然对数LN(2.718)0.999…
LOG10(x)以10为底对数LOG10(100)2.0
POWER(x, y)x的y次方POWER(2, 3)8
MOD(x, y)取余MOD(10, 3)1
PI()圆周率PI()3.14159…
RAND()随机数RAND()0~1之间

数学函数使用示例:

SELECTname,page_count,CEIL(page_count/200.0)ASest_reading_days,SQRT(page_count)AScomplexity_score,ROUND(page_count*0.02,2)ASestimated_priceFROMlibraryORDERBYestimated_priceDESC;

3.3 字符串函数

函数说明示例结果
CONCAT(s1, s2)字符串拼接CONCAT('a', 'b')"ab"
SUBSTRING(s, start, len)截取子串SUBSTRING('Hello', 1, 3)"Hel"
LENGTH(s)字符串长度LENGTH('Hello')5
CHAR_LENGTH(s)字符数CHAR_LENGTH('你好')2
UPPER(s)/UCASE(s)转大写UPPER('hello')"HELLO"
LOWER(s)/LCASE(s)转小写LOWER('HELLO')"hello"
LTRIM(s)去左空格LTRIM(' hi')"hi"
RTRIM(s)去右空格RTRIM('hi ')"hi"
TRIM(s)去两端空格TRIM(' hi ')"hi"
REPLACE(s, old, new)替换REPLACE('abc', 'b', 'x')"axc"
POSITION(sub IN s)查找子串位置POSITION('ll' IN 'Hello')3
LEFT(s, n)左取n个字符LEFT('Hello', 2)"He"
RIGHT(s, n)右取n个字符RIGHT('Hello', 2)"lo"

字符串函数使用示例:

SELECTname,UPPER(author)ASauthor_upper,CONCAT(author,' - ',name)ASbook_info,LENGTH(name)ASname_length,SUBSTRING(name,1,3)ASshort_nameFROMlibrary;

3.4 日期函数

函数说明示例
CURDATE()当前日期CURDATE()
NOW()当前日期时间NOW()
YEAR(date)提取年份YEAR(release_date)
MONTH(date)提取月份MONTH(release_date)
DAY(date)提取日DAY(release_date)
HOUR(date)提取小时HOUR(release_date)
MINUTE(date)提取分钟MINUTE(release_date)
SECOND(date)提取秒SECOND(release_date)
DAYOFWEEK(date)星期几(1-7)DAYOFWEEK(NOW())
DAYOFYEAR(date)一年中第几天DAYOFYEAR(NOW())
QUARTER(date)季度(1-4)QUARTER(release_date)
DATE_FORMAT(date, fmt)格式化日期DATE_FORMAT(NOW(), '%Y-%m')
DATE_TRUNC(unit, date)截断到指定单位DATE_TRUNC('month', NOW())

日期函数使用示例:

SELECTname,release_date,YEAR(release_date)ASrelease_year,MONTH(release_date)ASrelease_month,CONCAT(YEAR(release_date),'-Q',QUARTER(release_date))ASrelease_quarterFROMlibraryORDERBYrelease_dateDESC;

3.5 条件函数

函数说明示例
CASE WHEN ... THEN ... ELSE ... END条件判断见下方示例
IF(condition, true_val, false_val)条件选择IF(page_count > 500, 'long', 'short')
COALESCE(v1, v2, ...)返回第一个非NULL值COALESCE(nickname, name)
NULLIF(v1, v2)相等则返回NULLNULLIF(status, 'deleted')
ISNULL(expr)是否为NULLISNULL(phone)

CASE WHEN示例:

SELECTname,page_count,CASEWHENpage_count>=600THEN'超长篇'WHENpage_count>=400THEN'长篇'WHENpage_count>=200THEN'中篇'ELSE'短篇'ENDASbook_lengthFROMlibrary;

3.6 函数分类总览

分类代表函数说明
聚合函数AVG, COUNT, MAX, MIN, SUM对一组值计算,配合GROUP BY
数学函数ABS, CEIL, FLOOR, ROUND, SQRT数值计算
字符串函数CONCAT, SUBSTRING, UPPER, LOWER字符串处理
日期函数NOW, YEAR, MONTH, DAY, HOUR日期时间处理
条件函数CASE WHEN, IF, COALESCE条件判断
类型转换CAST, TRY_CAST数据类型转换
信息函数DATABASE, SCHEMA返回环境信息

四、综合查询实战

4.1 带分组和排序的复杂查询

SELECTauthor,COUNT(*)ASbook_count,AVG(page_count)ASavg_pages,SUM(page_count)AStotal_pagesFROMlibraryGROUPBYauthorHAVINGCOUNT(*)>=1ORDERBYavg_pagesDESCLIMIT10;

4.2 使用REST API执行

POST_sql?format=json{"query":"SELECT author, COUNT(*) AS book_count, AVG(page_count) AS avg_pages FROM library GROUP BY author ORDER BY avg_pages DESC"}

响应示例:

{"columns":[{"name":"author","type":"text"},{"name":"book_count","type":"long"},{"name":"avg_pages","type":"double"}],"rows":[["Frank Herbert",1,604.0],["James S.A. Corey",1,561.0],["Dan Simmons",1,482.0]],"status":200}

五、ES SQL的已知限制

5.1 不支持的SQL特性

ES SQL是对标准SQL的一个精简子集实现,以下特性不被支持:

限制类别不支持的特性替代方案
DMLINSERT、UPDATE、DELETE使用ES Index/Bulk API
DDLCREATE TABLE、ALTER TABLE使用ES Mapping API
JOININNER/LEFT/RIGHT JOIN使用ES父子文档或嵌套
子查询SELECT中的嵌套查询拆分为多次查询
UNIONUNION / UNION ALL使用ES多索引查询
事务BEGIN / COMMIT / ROLLBACKES不支持事务
视图CREATE VIEW不适用
存储过程PROCEDURE / FUNCTION不适用
窗口函数ROW_NUMBER / RANK / OVER使用ES聚合
递归查询WITH RECURSIVE不适用

5.2 其他限制

  • 不支持修改索引的mapping
  • 不支持跨索引的JOIN操作
  • GROUP BY不支持复杂表达式
  • 部分SQL函数可能因底层ES版本不同而有所差异
  • WHERE子句中的条件在底层转换为ES的bool query,某些复杂条件可能无法完美映射

六、SQL CLI工具

6.1 安装与配置

ES SQL CLI是一个命令行工具,提供交互式的SQL查询体验:

# 安装(需要Java环境)elasticsearch-sql-cli-7.x.x.zip# 解压后执行./elasticsearch-sql-cli http://localhost:9200

6.2 交互式使用

# 连接后进入交互式SQL Shellsql>SELECT*FROMlibraryLIMIT3;name|author|release_date|page_count---------------------|----------------------|-----------------------|------------Dune|Frank Herbert|1965-06-01T00:00:00.000Z|604Hyperion|Dan Simmons|1989-05-26T00:00:00.000Z|482Leviathan Wakes|James S.A.Corey|2011-06-02T00:00:00.000Z|561sql>DESCRIBElibrary;column|type-----------------|-----------------author|KEYWORD name|TEXTpage_count|LONG release_date|DATEsql>SHOWTABLES;name---------------library

6.3 CLI常用选项

# 指定用户名和密码./elasticsearch-sql-cli http://user:password@localhost:9200# 执行单条SQL./elasticsearch-sql-cli http://localhost:9200-q"SELECT COUNT(*) FROM library"# 指定输出格式./elasticsearch-sql-cli http://localhost:9200--format=csv

七、总结与最佳实践

核心要点

  1. 词法结构兼容ANSI SQL:关键字不区分大小写,标识符用双引号,字符串用单引号
  2. 函数体系丰富但有限:涵盖聚合、数学、字符串、日期、条件等常用函数
  3. 注意GROUP BY + HAVING组合:WHERE过滤行,HAVING过滤组,两者配合实现精细筛选
  4. 了解限制合理使用:ES SQL不支持JOIN和子查询,复杂场景需回到Query DSL

最佳实践清单

  • 使用SQL CLI进行数据探索和快速验证
  • 复杂查询先用Translate API查看翻译结果,确认语义正确
  • 使用参数化查询(params)防止SQL注入
  • 聚合查询务必设置LIMIT,避免结果集过大
  • 对于ES SQL不支持的特性,使用原生Query DSL替代
  • 定期使用DESCRIBE和SHOW COLUMNS了解索引结构变化

上一篇【第39篇】Elasticsearch SQL接口——用熟悉的SQL语法查询ES
下一篇【第41篇】为什么需要搜索引擎——关系数据库的搜索困境(明日更新,敬请期待)


http://www.jsqmd.com/news/886782/

相关文章:

  • 强化学习优化代码生成:环境插桩与自改进策略实践
  • 基于Arduino的智能蓝调节拍器:DIY音乐练习伴侣
  • 2026年5月天津国际高中推荐:五家专业评测择校案例性价比高 - 品牌推荐
  • 紧急预警:DeepSeek-v3商用许可协议重大更新!5月31日前未完成IP尽调的企业将丧失合规豁免权
  • 基于ESP32-Pico的智能蓝牙网关:改造传统暖气阀实现远程温控
  • 2026年LLM推理加速全景:量化、投机解码与KV Cache工程实战
  • 5分钟实现音乐自由:Mac端QQ音乐加密格式转换终极指南
  • 苏州拍婚纱照去哪些园林?本地人的场地选择建议 - eee888
  • Sangfor文件夹可以删除吗?【图文讲解】深信服文件夹残留清理?如何彻底删除深信服?Sangfor文件夹是什么?
  • PlayAI实时翻译落地全图谱(金融/医疗/制造三大硬核场景深度拆解)
  • Harness 中的自适应超时:基于百分位延迟
  • 基于RP2040 PIO的精准数字信号协议实现:微型解释器设计与应用
  • 英雄联盟回放播放神器:ROFLPlayer完整使用指南
  • 哪家天津国际高中专业?2026年5月推荐TOP5对比课程适配案例适用场景 - 品牌推荐
  • CANoe自动化测试进阶:手把手教你用XML文件管理CAPL测试用例(避坑Maintest函数)
  • 2026年澳洲留学服务机构哪个好:五家优选品牌深度解析 - 科技焦点
  • Midjourney烟雾分层控制失效?揭秘--raw模式下smoke density映射函数被重写的底层机制(附Python脚本自动校验Prompt有效性)
  • 【Midjourney云雾效果终极指南】:20年AI视觉工程师亲授5种高阶雾化参数组合,97%新手忽略的--v 6.2雾效权重陷阱
  • 【Elasticsearch从入门到精通】第39篇:Elasticsearch SQL接口——用熟悉的SQL语法查询ES
  • 基于TTP223的离线电容触摸开关设计:厨房灯控DIY方案
  • 2025-2026年久韵红家具电话查询:选购实木家具前需知事项与建议 - 品牌推荐
  • 2025-2026年久韵红家具电话查询:选购前请确认材质与定制服务范围 - 品牌推荐
  • Mac版Gemini应用今夏将新增“Spark“智能体与语音控制功能
  • 从经典到未来:社区驱动SDR硬件设计的十年演进与工程实践
  • 福州闽侯索赔律师排行:福州离婚律师、福州继承纠纷律师、福州连江律师、福州金牌律师、福州长乐律师、福州闽侯律师、福州个人维权律师选择指南 - 优质品牌商家
  • 基于STM32与LoRa的物联网节点设计:从硬件架构到低功耗实践
  • ssm高校普法系统(10101)
  • AI 充电式电动工具智能功率 MOSFET 完整选型方案
  • 为什么说AI革命才刚刚开始?从技术演进到商业落地的真实变化
  • QMCDecode终极指南:3步解锁QQ音乐加密文件,实现跨平台自由播放