在日常SQL开发中,我们经常使用
SELECT
、UPDATE
、DELETE
、INSERT
等常见关键字,但SQL标准中还有许多不常见却非常实用的关键字,这些关键字在特定场景下可以极大地优化查询性能或提供额外功能。本文将介绍一些鲜为人知但值得掌握的SQL关键字,并通过查询示例加深理解。
目录
1 LATERAL
2 WINDOW
3 MATCH_RECOGNIZE
4 DISTINCT ON
5 EXCEPT
6 UNNEST
7 ARRAY_AGG
8 CUBE
9 ROLLUP
10 JSON_TABLE
LATERAL
LATERAL
关键字用于在FROM子句的子查询中引用外部查询的列,这种机制允许SQL语句中的子查询获取与主查询相关的记录。通常情况下,子查询不能直接访问外部查询的列,而LATERAL
可以突破这一限制,使查询更加灵活。它在处理复杂的多表关联、动态过滤数据或展开JSON数据时非常有用。
id | name | contract |
---|---|---|
1 | Alice | {"type": "full-time"} |
2 | Bob | {"type": "part-time"} |
SELECT e.id, e.name, c.contract_type
FROM employees e,
LATERAL (
SELECT contract->>'type' AS contract_type
) c;
WINDOW
WINDOW
关键字用于定义窗口函数的窗口分区,使得多个窗口函数可以共享同一个窗口定义。这样可以避免在多个窗口函数中重复书写相同的PARTITION BY
和ORDER BY
子句,提高查询的可读性和效率。窗口函数常用于分析函数,例如计算累计总和、排名或移动平均值。
name | department | salary |
---|---|---|
Alice | Engineering | 8000.00 |
Bob | HR | 6000.00 |
SELECT name, department, salary,
AVG(salary) OVER emp_window AS avg_salary
FROM employees
WINDOW emp_window AS (PARTITION BY department ORDER BY hire_date);
MATCH_RECOGNIZE
MATCH_RECOGNIZE
关键字用于模式匹配查询,主要用于时间序列分析、数据流处理或检测异常模式。它允许定义模式规则,并使用PATTERN
和DEFINE
语句对数据进行模式识别,使得SQL能够像正则表达式一样匹配数据模式,特别适用于检测趋势、变化点或异常。
id | name | salary |
---|---|---|
1 | Alice | 8000.00 |
2 | Bob | 6000.00 |
SELECT * FROM employees
MATCH_RECOGNIZE (
ORDER BY hire_date
MEASURES id AS emp_id, name AS emp_name
PATTERN (A B)
DEFINE A AS salary > 7000, B AS salary < 7000
);
DISTINCT ON
DISTINCT ON
用于从重复数据中仅选取某个分组中的第一条记录。与GROUP BY
不同,它允许我们在有序数据集中获取特定类别的第一条数据,在去重的同时保留一定的排序逻辑,适用于获取最近更新的记录或按优先级筛选数据。
department | name | hire_date |
---|---|---|
Engineering | Alice | 2020-05-15 |
HR | Bob | 2019-07-23 |
SELECT DISTINCT ON (department) *
FROM employees
ORDER BY department, hire_date DESC;
EXCEPT
EXCEPT
关键字用于计算两个查询结果的差集,即返回出现在第一个查询但未出现在第二个查询中的记录。它类似于NOT IN
,但在处理大数据集时更高效,特别适用于数据去重和数据完整性验证。
name | department | salary |
---|---|---|
Alice | Engineering | 8000.00 |
David | Engineering | 9500.00 |
SELECT name FROM employees WHERE department = 'Engineering'
EXCEPT
SELECT name FROM employees WHERE salary > 9000;
UNNEST
UNNEST
用于展开数组或JSON数据,使其变为行格式,从而能够更方便地进行查询和分析。在数据库中,存储数组类型的数据时,UNNEST
可以帮助我们拆解数组,使得每个元素都能作为单独的行进行查询。
name | skills |
---|---|
Alice | {SQL, Python} |
Bob | {Java, C++} |
SELECT name, value AS contract_detail
FROM employees,
LATERAL UNNEST(string_to_array(contract::TEXT, ',')) AS contract_data(value);
ARRAY_AGG
ARRAY_AGG
是聚合函数之一,用于将多个行的值聚合成一个数组。它可以在查询时将相同类别的数据合并到一个数组中,适用于构建JSON结构或优化查询结果的输出格式。
department | name |
---|---|
Engineering | Alice |
Engineering | David |
SELECT department, ARRAY_AGG(name) AS employees
FROM employees
GROUP BY department;
CUBE
CUBE
关键字用于创建多维度聚合数据,使得在分组统计时可以同时计算不同组合的数据汇总。它是GROUP BY
的扩展,特别适用于报表生成和多层次数据分析。
department | salary | count |
---|---|---|
Engineering | 8000.00 | 1 |
HR | 6000.00 | 1 |
SELECT department, salary, COUNT(*)
FROM employees
GROUP BY CUBE(department, salary);
ROLLUP
ROLLUP
与GROUP BY
类似,但它允许在分组统计的基础上再增加总计行。它能够自动计算分组中的小计和总计数据,在数据分析和报表生成时非常有用。
department | salary_total |
---|---|
Engineering | 17500.00 |
HR | 6000.00 |
SELECT department, SUM(salary)
FROM employees
GROUP BY ROLLUP(department);
JSON_TABLE
JSON_TABLE
用于解析JSON数据,并将其转换为结构化表,使得SQL可以像查询普通表一样查询JSON数据。它适用于处理存储在数据库中的JSON格式数据,并能方便地对其进行筛选、聚合和关联查询。
json_data |
---|
{"id": 1, "name": "Alice"} |
{"id": 2, "name": "Bob"} |
SELECT * FROM JSON_TABLE(
'[{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]',
'$[*]' COLUMNS (
id INT PATH '$.id',
name VARCHAR(50) PATH '$.name'
)
);