
本书的结构
本书包括14章和两个附录。
•第1章介绍非常基本的查询语句。示例包括如何使用WHERE子句筛选结果集,为结果集里的列取别名,通过内嵌视图实现别名列引用,使用简单的条件逻辑,限制单个查询返回的记录行数,随机返回记录行,以及检索Null值。大多数示例都非常简单,但部分示例会再次出现在后续较为复杂的实例里。如果你是SQL 新手或者对这些用法不太熟悉,那么应该好好读一读这一章的内容。
•第2章提供了一些查询结果排序的实例。这一章介绍了ORDER BY子句,并将其用于查询结果排序。示例的难度逐步增加,从简单的单列排序到按照子字符串排序,再到按照条件表达式排序。
•第3章通过一些实例来演示如何合并多个表的数据。如果你是SQL 新手或不熟悉连接查询,我强烈建议你在阅读第5章及后续章节之前先读一读这一章的内容。连接查询几乎就是SQL 的全部内容,要学会SQL,你必须理解连接查询。这一章的示例包括执行内连接和外连接,识别笛卡儿积,执行基本的集合操作(差集、并集、交集),以及在连接查询中使用聚合函数。
•第4章分别提供了一些关于插入、更新和删除数据的实例。它们中的大多数都很直截了当(甚至可能让你觉得乏味)。然而,有一些操作可能对你非常有用,比如把一个表的若干行插入另一个表,更新数据时使用关联子查询,理解Null值的作用,以及掌握多表插入和MERGE命令等特性的用法。
•第5章通过一些实例讲解如何获取数据库的元数据信息。找出一个数据库的索引、约束和表往往非常有用。这些简单的例子帮助你获取关于数据库模式的信息。除此之外,这一章也包括一些动态SQL 示例,例如用SQL 生成新的SQL。
•第6章介绍了一些处理字符串的实例。SQL 的字符串解析能力并不出众,但基于数据库的大量专有函数,再加上一点点创意(通常要用到笛卡儿积),你就能完成不少工作。其中一些更加有趣的例子包括计算一个字符在某个字符串里出现过多少次,基于表的若干行生成列表,把列表和字符串转换成行数据,以及从一个字母和数字混合的字符串里提取数值和字符。
•第7章给出了一些常见的数字运算实例。这些例子极具通用性,并且能让你体会到窗口函数在解决涉及动态计算和聚合的问题时有多方便。这一章的示例包括计算累加值;计算平均数、中位数和众数;计算百分比;在聚合运算中排除Null值。
•第8章是涉及日期处理的两章中的第1章。对于日常任务来说,处理简单的日期运算十分重要。这一章给出的示例包括计算两个日期之间有多少个工作日,以不同的时间单位(天、月、年等)算出两个日期的差值,以及统计一年中有多少个星期一。
•第9章是涉及日期处理的第2章。你会发现日常工作中最为常见的日期操作实例,包括返回一年包含的所有天,计算闰年,算出一个月的第一天和最后一天,生成日历,以及填补一个日期范围里缺失的日期。
•第10章通过一些实例演示如何识别指定范围内的值,以及如何创建一系列的值。示例包括自动生成一系列行数据,填补一个数值范围里缺失的值,查找一个范围的开始值和结束值,以及查找连续的值。
•第11章中的例子有时被开发人员忽视,但对于日常开发工作来说至关重要。这些例子绝不比其他例子更难,但我却见到许多开发人员用非常低效的做法来解决同样的问题。这一章的示例包括查找“骑士值”,为结果集分页,跳过表里的某些行,逆序查找,检索靠前的n行,以及为查询结果排序。
•第12章提供了一些数据仓储和复杂报表生成领域常见的查询。我最初的愿望就是把这一章的内容作为本书的主体部分。这一章的示例包括行列互换(交叉报表),创建数据分组,创建直方图,计算出简单而完整的小计值,在一个动态的行数据窗口之上执行聚合计算,以及基于给定的时间单位做行数据分组。
•第13章介绍了一些与层次化有关的实例。无论采用何种建模方式,你总会在某个时刻需要做数据格式化工作,比如以树形结构或者父子关系形式展现出来。这一章提供的例子能够帮你完成这些任务。利用传统的SQL 创建树形结构的数据集并不容易,所以数据库厂商提供的专有函数在这一章里显得尤其有用。示例包括呈现数据的父子关系,从根节点到叶子节点逐层遍历,以及构造一个层次结构。
•第14章是各种实例的大杂烩,它们很难被归入某个问题领域,却既有趣又有用。这一章不同于其他各章之处在于,它只聚焦于数据库厂商提供的专有特性。每个实例只针对一种数据库而设,这是全书唯一这么做的一章。有两个原因促使我这么做:第一,我想让这一章的内容既有趣又带些许极客风格;第二,有些实例的存在就是为了突出某个数据库厂商的专有函数,因为在其他关系数据库管理系统里没有等价实现(示例包括SQL Server的PIVOT/UNPIVOT操作符和Oracle的MODEL子句)。在某些情况下,你能简单地改造一下这一章提供的解决方案,将其用于另一种数据库。
•附录A 带你复习窗口函数的相关知识,并且详细讨论了SQL 分组查询。你可能不熟悉窗口函数,附录A 可以帮助你快速入门。此外,根据我的经验,GROUP BY查询的使用一直令许多开发人员感到迷惑。附录A 精确定义了何为SQL 分组查询,并且给出了多种查询示例,以进一步解释该定义。接着,附录A 讨论了Null值对分组、聚合以及分区的影响,最后讨论了窗口函数中更难理解却功能强大的OVER子句(即开窗子句)。
•附录B 主要是向David Rozenshtein致敬,并把我在SQL 开发方面的成就归功于他。Rozenshtein的作品The Essence of SQL是我在课堂之外买的第一本SQL 书。我当时买这本书,并非为了应付考试。正是这本书教会了我如何用SQL 思考。时至今日,我仍把自己关于SQL 工作原理的许多心得体会归功于这本书。与我读过的其他SQL 书相比,它是如此与众不同,我为它能成为我的第一本SQL 书而充满感激之情。我在附录B 中重新审视了The Essence of SQL里出现过的一些查询语句,并给出了使用窗口函数实现的新解决方案。(在The Essence of SQL出版时,窗口函数尚未出现。)