4. SQL 基础回顾(一):数据库与表的概念、SELECT 语句基础、WHERE 条件过滤、ORDER BY 排序
在开始构建 Grafana 仪表盘之前,必须夯实 SQL 基础。本章将回顾关系型数据库的核心概念,并重点讲解最常用的查询语句结构,为后续的数据报表模板编写打下坚实基础。
4.1 数据库与表:数据存储的基石
关系型数据库(如 PostgreSQL、MySQL、SQLite)将数据组织为“表”(Table)。一个数据库可以包含多张表,每张表由行(Row / Record)和列(Column / Field)构成。
核心概念对比:
| 术语 | 说明 | 类比(Excel) |
|---|---|---|
| 数据库 (Database) | 存储数据的容器,包含多张表、视图、索引等对象。 | 一个工作簿文件 |
| 表 (Table) | 具有固定列结构的数据集合,是存储数据的基本单位。 | 工作簿中的一张工作表 |
| 列 (Column / Field) | 表中的一个字段,定义了数据类型(如整数、字符串、日期)。 | 工作表中的一列标题 |
| 行 (Row / Record) | 表中的一个数据条目,包含所有列的具体值。 | 工作表中的一行数据 |
| 主键 (Primary Key) | 唯一标识表中每一行的一列或多列组合,不允许重复或 NULL。 | 行号(但更严格) |
实战提示: 在 Grafana 的数据源配置中,你通常需要指定数据库名称和表名。理解表结构(列名、数据类型)是编写正确查询的第一步。
4.2 SELECT 语句基础:从表中检索数据
SELECT 是 SQL 中最核心的语句,用于从一个或多个表中查询数据。其基本语法结构如下:
SELECT 列名1, 列名2, ...
FROM 表名;
- 选择所有列: 使用
*通配符,但生产环境中建议明确列出列名以提高性能和可读性。 - 选择特定列: 列名之间用逗号分隔。
- 使用别名: 使用
AS关键字为列或表指定临时名称,增强可读性。
示例: 假设有一张名为
employees 的表,包含 id, name, department, salary 列。
-- 查询所有员工的所有信息
SELECT * FROM employees;
-- 查询所有员工的姓名和部门
SELECT name, department FROM employees;
-- 使用别名,将 salary 列显示为 "月薪"
SELECT name AS 姓名, salary AS 月薪 FROM employees;
注意: SQL 关键字(如 SELECT、FROM)不区分大小写,但通常约定俗成使用大写以增强可读性。字符串值需要使用单引号
' ' 括起来。
4.3 WHERE 条件过滤:精确筛选数据
WHERE 子句用于从表中筛选出满足特定条件的行。它紧跟在 FROM 子句之后。
SELECT 列名1, 列名2, ...
FROM 表名
WHERE 条件表达式;
常用比较运算符:
| 运算符 | 含义 | 示例 |
|---|---|---|
= |
等于 | WHERE department = 'Sales' |
<> 或 != |
不等于 | WHERE status <> 'inactive' |
>, < |
大于 / 小于 | WHERE salary > 50000 |
>=, <= |
大于等于 / 小于等于 | WHERE hire_date >= '2023-01-01' |
BETWEEN |
在某个范围内(包含边界) | WHERE salary BETWEEN 40000 AND 60000 |
LIKE |
模式匹配(% 匹配任意字符,_ 匹配单个字符) |
WHERE name LIKE 'J%' |
IN |
匹配值列表中的任意一个 | WHERE department IN ('Sales', 'Marketing') |
AND, OR, NOT |
逻辑运算符,用于组合多个条件 | WHERE department = 'Sales' AND salary > 50000 |
Grafana 场景: 在仪表盘变量中,你经常使用
WHERE 子句来过滤时间范围(如 WHERE time >= NOW() - INTERVAL '1 hour')或根据下拉列表选择的特定维度进行数据筛选。
-- 查询销售部门且薪资大于50000的员工姓名
SELECT name, salary
FROM employees
WHERE department = 'Sales' AND salary > 50000;
-- 查询名字以 'A' 开头的员工
SELECT * FROM employees
WHERE name LIKE 'A%';
4.4 ORDER BY 排序:让数据井然有序
ORDER BY 子句用于对查询结果集按照一个或多个列进行排序。它必须放在 WHERE 子句(如果存在)之后。
SELECT 列名1, 列名2, ...
FROM 表名
[WHERE 条件]
ORDER BY 列名1 [ASC | DESC], 列名2 [ASC | DESC], ...;
- ASC: 升序排列(默认,可省略)。数字从小到大,字母从 A 到 Z,日期从早到晚。
- DESC: 降序排列。数字从大到小,字母从 Z 到 A,日期从晚到早。
- 多列排序: 先按第一个列排序,如果值相同,再按第二个列排序,以此类推。
示例:
-- 按薪资升序排列所有员工
SELECT name, salary FROM employees
ORDER BY salary;
-- 按薪资降序排列,薪资相同则按名字升序排列
SELECT name, department, salary FROM employees
ORDER BY salary DESC, name ASC;
-- 结合 WHERE 使用:查询销售部门员工,按入职日期降序排列
SELECT name, hire_date FROM employees
WHERE department = 'Sales'
ORDER BY hire_date DESC;
性能提示: 对大量数据进行排序可能会消耗较多数据库资源。在 Grafana 中,如果数据量巨大,建议在数据库层面完成排序和聚合,而不是将原始数据拉到 Grafana 前端再排序。确保
ORDER BY 使用的列上有合适的索引。
4.5 综合实战:构建第一个报表查询
将本节知识点串联起来,编写一个完整的查询,用于后续 Grafana 仪表盘的数据源:
-- 目标:查询 2024 年所有已完成订单,按金额降序排列,显示订单号、客户名和金额
SELECT
o.order_id AS 订单号,
c.customer_name AS 客户名,
o.amount AS 金额
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id
WHERE o.status = 'completed'
AND o.order_date BETWEEN '2024-01-01' AND '2024-12-31'
ORDER BY o.amount DESC;