# Level 9 复杂的SQL查询

> 该章节思路：
>
> 通过lintcode复杂题目进行解析，按照下面的五个步骤层层讲解，最后加入一个lintcode复杂题目练习，融会贯通

当遇到复杂问题的时候，我们往往需要写较长较复杂的SQL查询语句，有可能会涉及到多个表的联结、嵌套以及多个条件的筛选，这对于没有太多经验或者不够自信的初学者来说非常困难。这里我们将复杂的SQL查询分解成简单的步骤，并教你一步一步如何完成复杂的SQL查询。

## 1. 明确你想要的结果

首先，从我们希望得到的结果开始，并写下SQL查询的预期结果集。了解您希望检索多少条记录，以及需要使用哪些表来创建您需要的结果。

## 2. 将你的查询分解成可控的几个部分

编写复杂的SQL查询，下一步就是要对表中的不同字段以及每个字段之间的关系有一个很好的了解。它们是一对一的关系还是一对多的关系？在这里，一个ER（实体/关系）图是很有用的，因为它可以快速地为你显示这些关系。确保你知道连接所需的字段。

记住，你不必一次写完整个SQL查询。先确定在你的两个表上使用哪种联结方式(JOIN、RIGHT JOIN、OUTTER JOIN)，然后从这里引入其他表。记住，复杂的查询通常只是简单SQL查询的集合。在每个阶段测试较简单的查询，以确保你得到了你需要的结果

下图对于该步骤的复杂SQL语句书写很有帮助

![img](https://jiuzhang.feishu.cn/space/api/box/stream/download/asynccode/?code=YWRlNDc4NzUzNzQxODI4Y2M5NThmNjM5NDVhMGE0MzJfVWcxWVltZ3BhMnpseDdoenhjQXE1Z3BUTVRmNTh2YmdfVG9rZW46Ym94Y245ZG0zSFg2ZGRDV3dNY1JkdHJYYU5oXzE2MTQwNjQxNjc6MTYxNDA2Nzc2N19WNA)

一旦你创建了查询，记得每次添加新表时都需要重新测试，这是能确保你仍能得到你想要结果的一个检查。

## 3. 确定是否需要汇总/排序结果集

如果您需要通过一个或多个列对结果集进行分组，那么您可能需要使用 GROUP BY。你可能还需要使用一个聚合函数，如COUNT, MAX, MIN, SUM或AVG。另外，如果结果的顺序很重要，那么不要忘记在语句末尾的ORDER和ASC/DESC。

## 4. 使得语句更于阅读

在需要的地方缩进SQL语句，必要的时候也可以添加注释。不要在不需要的地方添加注释，因为过多的注释会使代码的可读性降低，并使SQL语句的长度超过需要的长度。请记住，SQL语句越长，使用的带宽就越多，语句执行的时间就越长。

如果大家对表名使用同样的约定（如first\_name，FirstName，firstName），并将SQL关键字也大写，那么SQL也会更容易理解。(如：SELECT first\_name from MEMBERS )。

另一个要注意的是不要使&#x7528;*（如SELECT* from MEMBERS）。如果给出了字段名，查询就会容易理解得多，而且在不需要使用*的时候，使用*也会减慢查询的速度。

## 5. 其他需要考虑的事项

如果你的查询非常复杂，你可能会发现为你的查询使用存储过程会更容易（但不一定更好），但是在你这样做之前，有一些要点需要考虑:

* 迁移到别的DBMS会没那么方便
* 如果有问题非常难以debug
* 降低了应用服务器的负荷但是增加了数据服务器的负荷

你也可以使用更简单的SQL语句，然后在你的应用程序代码中循环处理结果，在需要时调用更多的SQL语句。我不推荐这种方法，因为这是一种粗暴的行为，会导致代码混乱。最好的办法是练习SQL，并熟练掌握它，而不是采用一种变通的方法。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://liancode.gitbook.io/sql/level-9/level9-fu-za-de-sql-cha-xun.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
