返回首页

如何编写SQL查询:教程与示例

本教程全面介绍如何编写SQL查询,涵盖SELECT和WHERE等基础语句、GROUP BY和HAVING的高级聚合、表连接、子查询以及可读性最佳实践。读者将获得为任何关系数据库系统编写高效、可维护SQL查询的实用技能。

掌握SQL查询:带代码示例的分步教程
Advertisement 728x90

如何编写SQL查询:实用教程与示例

结构化查询语言(SQL)是与关系型数据库通信的通用方法,但编写有效的查询远不止拼凑几个关键词那么简单。这是一个结合逻辑、对数据的清晰理解以及数据库运行原理的过程。本教程将教你编写不仅正确,而且高效、易读、易维护的SQL查询,无论你使用哪种数据库系统。

你将学到什么

通过本指南,你将能够从头构建SQL查询,精确地过滤、排序和聚合数据。你将理解查询执行顺序的重要性,并掌握编写专业级复杂SQL语句的清晰思路。编写SQL查询是一个结构化过程,子句的编写顺序与数据库引擎的执行顺序不同。

基础:SELECT语句

数据检索的核心是SELECT语句。它告诉数据库你想要查看哪些信息以及在哪里找到它们。查询最基本的形式由SELECTFROM子句组成。

Google AdInline article slot
SELECT column1, column2
FROM table_name;

例如,要从维度表中检索员工编号和姓氏,你可以这样写:

SELECT EmployeeKey, LastName
FROM DimEmployee;

虽然SELECT *可能很方便快速查看所有列,但在生产代码中通常被视为不良实践,因为它可能返回不必要的数据,影响性能,并在表结构变化时破坏应用程序。始终指定你需要的列。

使用WHERE子句构建逻辑

要过滤数据并仅检索相关行,你需要使用WHERE子句。它指定行必须满足的搜索条件才能包含在结果中。WHERE子句在查询结构中位于FROM子句之后。

Google AdInline article slot

你可以使用各种运算符来构建强大的搜索条件。例如,要查找名为"Smith"的特定员工,可以使用简单的相等比较:

SELECT EmployeeKey, LastName
FROM DimEmployee
WHERE LastName = 'Smith';

对于更复杂的过滤,你可以使用LIKE运算符进行模式匹配。以下查询查找所有姓氏包含"Smi"模式的员工:

SELECT EmployeeKey, LastName
FROM DimEmployee
WHERE LastName LIKE '%Smi%';

逻辑运算符如ANDOR允许你组合多个条件。你可以使用AND确保所有条件都必须满足,使用OR表示任一条件为真即可。例如,要查找满足多个条件的行,你可以这样写:

Google AdInline article slot
SELECT EmployeeKey, LastName
FROM DimEmployee
WHERE EmployeeKey <= 500
      AND LastName LIKE '%Smi%';

需要注意的是,WHERE子句过滤的是单个行,不能过滤聚合结果。IN运算符是一种简洁的方式,用于检查值是否与列表中的任何值匹配,而BETWEEN用于查找范围内的值。

-- 使用 IN
SELECT EmployeeKey, LastName
FROM DimEmployee
WHERE LastName IN ('Smith', 'Godfrey', 'Johnson');

-- 使用 BETWEEN
SELECT EmployeeKey, LastName
FROM DimEmployee
WHERE EmployeeKey BETWEEN 100 AND 200;

根据微软文档,搜索条件中可以包含的谓词数量没有限制,这允许高度具体和复杂的过滤逻辑。

塑造和组织你的结果

过滤数据后,你通常希望组织数据以提高可读性或执行计算。ORDER BY子句根据一个或多个列对结果集进行排序。它位于SELECT语句之后,可以指定升序(ASC,默认)或降序(DESC)。要删除结果集中的重复行,可以在SELECT后立即使用DISTINCT关键字。

SELECT DISTINCT JobTitle
FROM HumanResources.Employee
ORDER BY JobTitle;

GROUP BY子句是数据聚合的强大工具。它将具有相同值的行分组到指定列中,允许你执行汇总操作,如SUMAVGCOUNTMAXMIN。例如,要查找每个销售订单的总计,你可以按SalesOrderID分组并对行总计求和:

SELECT SalesOrderID,
    SUM(LineTotal) AS SubTotal
FROM Sales.SalesOrderDetail
GROUP BY SalesOrderID
ORDER BY SalesOrderID;

当你想要过滤GROUP BY的结果时,必须使用HAVING子句。与在分组前过滤单个行的WHERE子句不同,HAVING在聚合发生后过滤分组。

SELECT ProductID
FROM Sales.SalesOrderDetail
GROUP BY ProductID
HAVING AVG(OrderQty) > 5;

这些子句的编写顺序至关重要。标准SQL查询遵循以下结构:SELECTFROMWHEREGROUP BYHAVINGORDER BY

高级技巧:连接与子查询

数据通常存储在多个表中,你可以使用JOIN子句将它们组合在一起。INNER JOIN检索两个表中满足连接条件的记录。例如,你可以将Product表与SalesOrderDetail表连接,以获取产品信息及其销售数据。

子查询,即嵌套查询,是另一个查询内部的查询。它们对于依赖于另一个操作结果的数据操作和分析非常有用。相关子查询是一种特别复杂的类型,其中内部查询依赖于外部查询的值,为处理的每一行重复执行。EXISTS关键字通常与相关子查询一起使用,用于测试子查询中是否存在行。

编写可读的SQL

编写能工作的SQL只是成功了一半;编写可维护的SQL是专业上的必要。遵循以下最佳实践,确保你的查询成为协作的工具,而不是混乱的源头:

  • 关键词大写: 使用大写字母表示SQL关键词,如SELECTFROMWHEREJOIN。这使它们与列名和表名区分开来,使查询更易于扫描。
  • 使用换行和缩进: 将每个主要子句放在新行,并使用缩进来显示子查询或连接结构。这种视觉层次结构澄清了复杂的逻辑。
  • 添加有意义的注释: 使用--添加注释,解释查询背后的原因,而不是内容。这对未来的你和同事来说非常宝贵。
  • 使用描述性别名: 当使用AS重命名列或缩短表名时,选择有意义的别名。避免使用模糊的名称,如t1a

来源

  1. WHERE (Transact-SQL) - SQL Server
  2. T-SQL教程:编写Transact-SQL语句
  3. SELECT示例 (Transact-SQL)
  4. PostgreSQL:文档:17:2.5. 查询表
  5. 生态学家的数据管理SQL:使用查询访问数据
  6. EXISTS (Transact-SQL) - SQL Server
  7. Transact-SQL语法约定 (Transact-SQL)
  8. 如何编写任何人都能理解的SQL查询

— Editorial Team

Advertisement 728x90

继续阅读