SQL查询语法知识梳理总结
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>基本查询</li><li>
条件查询<ul class="second_class_ul"><li>
常用的条件表达式</li></ul></li><li>
投影查询<ul class="second_class_ul"></ul></li><li>
排序<ul class="second_class_ul"></ul></li><li>
分页查询<ul class="second_class_ul"></ul></li><li>
聚合查询<ul class="second_class_ul"><li>
分组</li></ul></li><li>
多表查询<ul class="second_class_ul"></ul></li><li>
连接查询<ul class="second_class_ul"><li>
小结</li></ul></li></ul></div><div id="navCategory">
<h5 class="catalogue">
目录</h5>
<ul class="first_class_ul">
<li>
基本查询</li>
<li>
条件查询
<ul class="second_class_ul">
<li>
常用的条件表达式</li>
</ul>
</li>
<li>
投影查询
<ul class="second_class_ul"></ul>
</li>
<li>
排序
<ul class="second_class_ul"></ul>
</li>
<li>
分页查询
<ul class="second_class_ul"></ul>
</li>
<li>
聚合查询
<ul class="second_class_ul">
<li>
分组</li>
</ul>
</li>
<li>
多表查询
<ul class="second_class_ul"></ul>
</li>
<li>
连接查询
<ul class="second_class_ul">
<li>
小结</li>
</ul>
</li>
</ul>
</div>
<p class="maodian">
</p>
<p class="maodian"></p><h2>
基本查询</h2>
<div class="jb51code">
<div>
<div class="syntaxhighlightersql" id="highlighter_967605">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="sql keyword">SELECT</code> <code class="sql plain">* </code><code class="sql keyword">FROM</code> <code class="sql plain"><表名></code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<p>
select也可以用作计算,但不是他的强项,select语句可以用来判断数据库的连接是否有效例如:许多检测工具会执行一条<code>SELECT 1;</code>来测试数据库连接。</p>
<p class="maodian">
</p>
<p class="maodian"></p><h2>
条件查询</h2>
<div class="jb51code">
<div>
<div class="syntaxhighlightersql" id="highlighter_432994">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="sql keyword">SELECT</code> <code class="sql plain">* </code><code class="sql keyword">FROM</code> <code class="sql plain"><表名> </code><code class="sql keyword">WHERE</code> <code class="sql plain"><条件表达式></code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<p>
条件表达式可以用<条件1> AND <条件2>表达满足条件1并且满足条件2。</p>
<p>
第二种条件是<条件1> OR <条件2>,表示满足条件1或者满足条件2。</p>
<p>
第三种条件是NOT <条件>,表示“不符合该条件”的记录。例如,写一个“不是2班的学生”这个条件,可以先写出“是2班的学生”:<code>class_id = 2</code>,再加上<code>NOT</code>:<code>NOT class_id = 2</code>:</p>
<p>
上述<code>NOT</code>条件<code>NOT class_id = 2</code>其实等价于<code>class_id <> 2</code>,因此,<code>NOT</code>查询不是很常用。</p>
<p>
要组合三个或者更多的条件,就需要用小括号<code>()</code>表示如何进行条件运算。例如,编写一个复杂的条件:分数在80以下或者90以上,并且是男生:</p>
<div class="jb51code">
<div>
<div class="syntaxhighlightersql" id="highlighter_381153">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="sql keyword">SELECT</code> <code class="sql plain">* </code><code class="sql keyword">FROM</code> <code class="sql plain">students </code><code class="sql keyword">WHERE</code> <code class="sql plain">(score < 80 </code><code class="sql color1">OR</code> <code class="sql plain">score > 90) </code><code class="sql color1">AND</code> <code class="sql plain">gender = </code><code class="sql string">'M'</code><code class="sql plain">;</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<p>
如果不加括号,条件运算按照<code>NOT</code>、<code>AND</code>、<code>OR</code>的优先级进行,即<code>NOT</code>优先级最高,其次是<code>AND</code>,最后是<code>OR</code>。加上括号可以改变优先级。</p>
<p class="maodian">
</p>
<p class="maodian"></p><h3>
常用的条件表达式</h3>
<table>
<thead><tr>
<th>
条件</th>
<th>
表达式举例1</th>
<th>
表达式举例2</th>
<th>
说明</th>
</tr></thead>
<tbody>
<tr>
<td>
使用=判断相等</td>
<td>
score = 80</td>
<td>
name = ‘abc'</td>
<td>
字符串需要用单引号括起来</td>
</tr>
<tr>
<td>
使用>判断大于</td>
<td>
score > 80</td>
<td>
name > ‘abc'</td>
<td>
字符串比较根据ASCII码,中文字符比较根据数据库设置</td>
</tr>
<tr>
<td>
使用>=判断大于或相等</td>
<td>
score >= 80</td>
<td>
name >= ‘abc'</td>
<td>
</td>
</tr>
<tr>
<td>
使用<判断小于</td>
<td>
score < 80</td>
<td>
name <= ‘abc'</td>
<td>
</td>
</tr>
<tr>
<td>
使用<=判断小于或相等</td>
<td>
score <= 80</td>
<td>
name <= ‘abc'</td>
<td>
</td>
</tr>
<tr>
<td>
使用<>判断不相等</td>
<td>
score <> 80</td>
<td>
name <> ‘abc'</td>
<td>
</td>
</tr>
<tr>
<td>
使用LIKE判断相似</td>
<td>
name LIKE ‘ab%'</td>
<td>
name LIKE ‘%bc%'</td>
<td>
%表示任意字符,例如'ab%‘将匹配'ab',‘abc',‘abcd'</td>
</tr>
</tbody>
</table>
<p class="maodian">
</p>
<p class="maodian"></p><h2>
投影查询</h2>
<p>
如果我们只希望返回某些列的数据,而不是所有列的数据,我们可以用<code>SELECT 列1, 列2, 列3 FROM ...</code>,让结果集仅包含指定列。这种操作称为投影查询。</p>
<div class="jb51code">
<div>
<div class="syntaxhighlightersql" id="highlighter_436242">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="sql keyword">SELECT</code> <code class="sql plain">id, score, </code><code class="sql keyword">name</code> <code class="sql keyword">FROM</code> <code class="sql plain">students;</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<p>
这样返回的结果集就只包含了我们指定的列,并且,结果集的列的顺序和原表可以不一样。</p>
<blockquote>
<p>
使用SELECT 列1, 列2, 列3 FROM ...时,还可以给每一列起个别名,</p>
<p>
这样,结果集的列名就可以与原表的列名不同。</p>
<p>
它的语法是SELECT 列1 别名1, 列2 别名2, 列3 别名3 FROM ...</p>
</blockquote>
<p>
例如,以下<code>SELECT</code>语句将列名<code>score</code>重命名为<code>points</code>,而<code>id</code>和<code>name</code>列名保持不变:</p>
<div class="jb51code">
<div>
<div class="syntaxhighlightersql" id="highlighter_37211">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="sql keyword">SELECT</code> <code class="sql plain">id, score points, </code><code class="sql keyword">name</code> <code class="sql keyword">FROM</code> <code class="sql plain">students;</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<p>
投影查询同样可以接<code>WHERE</code>条件,实现复杂的查询。</p>
<div class="jb51code">
<div>
<div class="syntaxhighlightersql" id="highlighter_888524">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="sql keyword">SELECT</code> <code class="sql plain">id, score points, </code><code class="sql keyword">name</code> <code class="sql keyword">FROM</code> <code class="sql plain">students </code><code class="sql keyword">WHERE</code> <code class="sql plain">gender = </code><code class="sql string">'M'</code><code class="sql plain">;</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<p class="maodian">
</p>
<p class="maodian"></p><h2>
排序</h2>
<p>
我们使用SELECT查询时,默认查询结果集通常是按照<code>id</code>排序的,也就是根据主键排序。这也是大部分数据库的做法。如果我们要根据其他条件排序怎么办?可以加上<code>ORDER BY</code>子句。例如按照成绩从低到高进行排序:</p>
<div class="jb51code">
<div>
<div class="syntaxhighlightersql" id="highlighter_343660">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="sql keyword">SELECT</code> <code class="sql plain">id, </code><code class="sql keyword">name</code><code class="sql plain">, gender, score </code><code class="sql keyword">FROM</code> <code class="sql plain">students </code><code class="sql keyword">ORDER</code> <code class="sql keyword">BY</code> <code class="sql plain">score;</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<p>
如果要反过来,按照成绩从高到底排序,我们可以加上<code>DESC</code>表示“倒序”:</p>
<div class="jb51code">
<div>
<div class="syntaxhighlighterpy" id="highlighter_646705">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="py plain">SELECT </code><code class="py functions">id</code><code class="py plain">, name, gender, score FROM students ORDER BY score DESC;</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<p>
如果<code>score</code>列有相同的数据,要进一步排序,可以继续添加列名。例如,使用<code>ORDER BY score DESC, gender</code>表示先按<code>score</code>列倒序,如果有相同分数的,再按<code>gender</code>列排序:</p>
<div class="jb51code">
<div>
<div class="syntaxhighlightersql" id="highlighter_856047">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="sql keyword">SELECT</code> <code class="sql plain">id, </code><code class="sql keyword">name</code><code class="sql plain">, gender, score </code><code class="sql keyword">FROM</code> <code class="sql plain">students </code><code class="sql keyword">ORDER</code> <code class="sql keyword">BY</code> <code class="sql plain">score </code><code class="sql keyword">DESC</code><code class="sql plain">, gender;</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<p>
默认的排序规则是<code>ASC</code>:“升序”,即从小到大。<code>ASC</code>可以省略,即<code>ORDER BY score ASC</code>和<code>ORDER BY score</code>效果一样。</p>
<p>
如果有<code>WHERE</code>子句,那么<code>ORDER BY</code>子句要放到<code>WHERE</code>子句后面。例如,查询一班的学生成绩,并按照倒序排序:</p>
<div class="jb51code">
<div>
<div class="syntaxhighlightersql" id="highlighter_398777">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
<div class="line number2 index1 alt1">
2</div>
<div class="line number3 index2 alt2">
3</div>
<div class="line number4 index3 alt1">
4</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="sql keyword">SELECT</code> <code class="sql plain">id, </code><code class="sql keyword">name</code><code class="sql plain">, gender, score</code>
</div>
<div class="line number2 index1 alt1">
<code class="sql keyword">FROM</code> <code class="sql plain">students</code>
</div>
<div class="line number3 index2 alt2">
<code class="sql keyword">WHERE</code> <code class="sql plain">class_id = 1</code>
</div>
<div class="line number4 index3 alt1">
<code class="sql keyword">ORDER</code> <code class="sql keyword">BY</code> <code class="sql plain">score </code><code class="sql keyword">DESC</code><code class="sql plain">;</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<p class="maodian">
</p>
<p class="maodian"></p><h2>
分页查询</h2>
<p>
使用SELECT查询时,如果结果集数据量很大,比如几万行数据,放在一个页面显示的话数据量太大,不如分页显示,每次显示100条。</p>
<p>
要实现分页功能,实际上就是从结果集中显示第1100条记录作为第1页,显示第101200条记录作为第2页,以此类推。</p>
<p>
因此,分页实际上就是从结果集中“截取”出第M~N条记录。这个查询可以通过<code>LIMIT <M> OFFSET <N></code>子句实现。</p>
<p>
<code>OFFSET</code>是可选的,如果只写<code>LIMIT 15</code>,那么相当于<code>LIMIT 15 OFFSET 0</code>。</p>
<p>
在MySQL中,<code>LIMIT 15 OFFSET 30</code>还可以简写成<code>LIMIT 30, 15</code>。</p>
<p>
使用<code>LIMIT <M> OFFSET <N></code>分页时,随着<code>N</code>越来越大,查询效率也会越来越低。</p>
<div class="jb51code">
<div>
<div class="syntaxhighlightersql" id="highlighter_321016">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
<div class="line number2 index1 alt1">
2</div>
<div class="line number3 index2 alt2">
3</div>
<div class="line number4 index3 alt1">
4</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="sql keyword">SELECT</code> <code class="sql plain">id, </code><code class="sql keyword">name</code><code class="sql plain">, gender, score</code>
</div>
<div class="line number2 index1 alt1">
<code class="sql keyword">FROM</code> <code class="sql plain">students</code>
</div>
<div class="line number3 index2 alt2">
<code class="sql keyword">ORDER</code> <code class="sql keyword">BY</code> <code class="sql plain">score </code><code class="sql keyword">DESC</code>
</div>
<div class="line number4 index3 alt1">
<code class="sql plain">LIMIT 3 OFFSET 0;</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<p class="maodian">
</p>
<p class="maodian"></p><h2>
聚合查询</h2>
<p>
如果我们要统计一张表的数据量,例如,想查询<code>students</code>表一共有多少条记录,可以使用SQL内置的<code>COUNT()</code>函数查询:</p>
<div class="jb51code">
<div>
<div class="syntaxhighlightersql" id="highlighter_269872">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="sql keyword">SELECT</code> <code class="sql color2">COUNT</code><code class="sql plain">(*) </code><code class="sql keyword">FROM</code> <code class="sql plain">students;</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<p>
<code>COUNT(*)</code>表示查询所有列的行数,要注意聚合的计算结果虽然是一个数字,但查询的结果仍然是一个二维表,只是这个二维表只有一行一列,并且列名是<code>COUNT(*)</code>。</p>
<p>
通常,使用聚合查询时,我们应该给列名设置一个别名,便于处理结果:</p>
<div class="jb51code">
<div>
<div class="syntaxhighlightersql" id="highlighter_653692">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="sql keyword">SELECT</code> <code class="sql color2">COUNT</code><code class="sql plain">(*) num </code><code class="sql keyword">FROM</code> <code class="sql plain">students;</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<p>
另外注意,聚合查询同样可以使用<code>WHERE</code>条件,因此我们可以方便地统计出有多少男生、多少女生、多少80分以上的学生等:</p>
<div class="jb51code">
<div>
<div class="syntaxhighlightersql" id="highlighter_663173">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="sql keyword">SELECT</code> <code class="sql color2">COUNT</code><code class="sql plain">(*) boys </code><code class="sql keyword">FROM</code> <code class="sql plain">students </code><code class="sql keyword">WHERE</code> <code class="sql plain">gender = </code><code class="sql string">'M'</code><code class="sql plain">;<br></code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<p>
除了<code>COUNT()</code>函数外,SQL还提供了如下聚合函数:</p>
<table>
<thead><tr>
<th>
函数</th>
<th>
说明</th>
</tr></thead>
<tbody>
<tr>
<td>
SUM</td>
<td>
计算某一列的合计值,该列必须为数值类型</td>
</tr>
<tr>
<td>
AVG</td>
<td>
计算某一列的平均值,该列必须为数值类型</td>
</tr>
<tr>
<td>
MAX</td>
<td>
计算某一列的最大值</td>
</tr>
<tr>
<td>
MIN</td>
<td>
计算某一列的最小值</td>
</tr>
</tbody>
</table>
<p>
注意,<code>MAX()</code>和<code>MIN()</code>函数并不限于数值类型。如果是字符类型,<code>MAX()</code>和<code>MIN()</code>会返回排序最后和排序最前的字符。</p>
<p>
要统计男生的平均成绩,我们用下面的聚合查询:</p>
<div class="jb51code">
<div>
<div class="syntaxhighlightersql" id="highlighter_655850">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="sql keyword">SELECT</code> <code class="sql color2">AVG</code><code class="sql plain">(score) average </code><code class="sql keyword">FROM</code> <code class="sql plain">students </code><code class="sql keyword">WHERE</code> <code class="sql plain">gender = </code><code class="sql string">'M'</code><code class="sql plain">;</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<p>
要特别注意:如果聚合查询的<code>WHERE</code>条件没有匹配到任何行,<code>COUNT()</code>会返回0,而<code>SUM()</code>、<code>AVG()</code>、<code>MAX()</code>和<code>MIN()</code>会返回<code>NULL</code></p>
<p class="maodian">
</p>
<p class="maodian"></p><h3>
分组</h3>
<blockquote>
<p>
如果我们要统计一班的学生数量,我们知道,可以用</p>
<p>
SELECT COUNT(*) num FROM students WHERE class_id = 1;</p>
</blockquote>
<p>
如果要继续统计二班、三班的学生数量,难道必须不断修改<code>WHERE</code>条件来执行<code>SELECT</code>语句吗?</p>
<p>
对于聚合查询,SQL还提供了“分组聚合”的功能。我们观察下面的聚合查询:</p>
<div class="jb51code">
<div>
<div class="syntaxhighlightersql" id="highlighter_598668">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="sql keyword">SELECT</code> <code class="sql color2">COUNT</code><code class="sql plain">(*) num </code><code class="sql keyword">FROM</code> <code class="sql plain">students </code><code class="sql keyword">GROUP</code> <code class="sql keyword">BY</code> <code class="sql plain">class_id;</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<p>
执行这个查询,<code>COUNT()</code>的结果不再是一个,而是3个,这是因为,<code>GROUP BY</code>子句指定了按<code>class_id</code>分组,因此,执行该<code>SELECT</code>语句时,会把<code>class_id</code>相同的行先分组,再分别计算,因此,得到了3行结果。</p>
<p>
但是这3行结果分别是哪三个班级的,不好看出来,所以我们可以把<code>class_id</code>列也放入结果集中:</p>
<div class="jb51code">
<div>
<div class="syntaxhighlightersql" id="highlighter_820919">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="sql keyword">SELECT</code> <code class="sql plain">class_id, </code><code class="sql color2">COUNT</code><code class="sql plain">(*) num </code><code class="sql keyword">FROM</code> <code class="sql plain">students </code><code class="sql keyword">GROUP</code> <code class="sql keyword">BY</code> <code class="sql plain">class_id;</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<p>
但是不可把<code>name</code>放入结果集,因为在任意一个分组中,只有<code>class_id</code>都相同,<code>name</code>是不同的,SQL引擎不能把多个<code>name</code>的值放入一行记录中。因此,聚合查询的列中,只能放入分组的列。</p>
<p>
也可以使用多个列进行分组。例如,我们想统计各班的男生和女生人数:</p>
<div class="jb51code">
<div>
<div class="syntaxhighlightersql" id="highlighter_266201">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="sql keyword">SELECT</code> <code class="sql plain">class_id, gender, </code><code class="sql color2">COUNT</code><code class="sql plain">(*) num </code><code class="sql keyword">FROM</code> <code class="sql plain">students </code><code class="sql keyword">GROUP</code> <code class="sql keyword">BY</code> <code class="sql plain">class_id, gender;</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<p class="maodian">
</p>
<p class="maodian"></p><h2>
多表查询</h2>
<p>
SELECT查询不但可以从一张表查询数据,还可以从多张表同时查询数据。</p>
<blockquote>
<p>
查询多张表的语法是:SELECT * FROM <表1> <表2>。</p>
</blockquote>
<p>
例如,同时从<code>students</code>表和<code>classes</code>表的“乘积”,即查询数据,可以这么写:</p>
<div class="jb51code">
<div>
<div class="syntaxhighlightersql" id="highlighter_153443">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="sql keyword">SELECT</code> <code class="sql plain">* </code><code class="sql keyword">FROM</code> <code class="sql plain">students, classes;</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<p>
这种一次查询两个表的数据,查询的结果也是一个二维表,它是<code>students</code>表和<code>classes</code>表的“乘积”,即<code>students</code>表的每一行与<code>classes</code>表的每一行都两两拼在一起返回。结果集的列数是<code>students</code>表和<code>classes</code>表的列数之和,行数是<code>students</code>表和<code>classes</code>表的行数之积。</p>
<p>
这种多表查询又称笛卡尔查询,使用笛卡尔查询时要非常小心,由于结果集是目标表的行数乘积,对两个各自有100行记录的表进行笛卡尔查询将返回1万条记录,对两个各自有1万行记录的表进行笛卡尔查询将返回1亿条记录。</p>
<p>
你可能还注意到了,上述查询的结果集有两列<code>id</code>和两列<code>name</code>,两列<code>id</code>是因为其中一列是<code>students</code>表的<code>id</code>,而另一列是<code>classes</code>表的<code>id</code>,但是在结果集中,不好区分。两列<code>name</code>同理</p>
<p>
要解决这个问题,我们仍然可以利用投影查询的“设置列的别名”来给两个表各自的<code>id</code>和<code>name</code>列起别名:</p>
<div class="jb51code">
<div>
<div class="syntaxhighlightersql" id="highlighter_121331">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
<div class="line number2 index1 alt1">
2</div>
<div class="line number3 index2 alt2">
3</div>
<div class="line number4 index3 alt1">
4</div>
<div class="line number5 index4 alt2">
5</div>
<div class="line number6 index5 alt1">
6</div>
<div class="line number7 index6 alt2">
7</div>
<div class="line number8 index7 alt1">
8</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="sql keyword">SELECT</code>
</div>
<div class="line number2 index1 alt1">
<code class="sql spaces"> </code><code class="sql plain">students.id sid,</code>
</div>
<div class="line number3 index2 alt2">
<code class="sql spaces"> </code><code class="sql plain">students.</code><code class="sql keyword">name</code><code class="sql plain">,</code>
</div>
<div class="line number4 index3 alt1">
<code class="sql spaces"> </code><code class="sql plain">students.gender,</code>
</div>
<div class="line number5 index4 alt2">
<code class="sql spaces"> </code><code class="sql plain">students.score,</code>
</div>
<div class="line number6 index5 alt1">
<code class="sql spaces"> </code><code class="sql plain">classes.id cid,</code>
</div>
<div class="line number7 index6 alt2">
<code class="sql spaces"> </code><code class="sql plain">classes.</code><code class="sql keyword">name</code> <code class="sql plain">cname</code>
</div>
<div class="line number8 index7 alt1">
<code class="sql keyword">FROM</code> <code class="sql plain">students, classes;</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<p>
注意,多表查询时,要使用<code>表名.列名</code>这样的方式来引用列和设置别名,这样就避免了结果集的列名重复问题。但是,用<code>表名.列名</code>这种方式列举两个表的所有列实在是很麻烦,所以SQL还允许给表设置一个别名,让我们在投影查询中引用起来稍微简洁一点:</p>
<div class="jb51code">
<div>
<div class="syntaxhighlightersql" id="highlighter_631504">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
<div class="line number2 index1 alt1">
2</div>
<div class="line number3 index2 alt2">
3</div>
<div class="line number4 index3 alt1">
4</div>
<div class="line number5 index4 alt2">
5</div>
<div class="line number6 index5 alt1">
6</div>
<div class="line number7 index6 alt2">
7</div>
<div class="line number8 index7 alt1">
8</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="sql keyword">SELECT</code>
</div>
<div class="line number2 index1 alt1">
<code class="sql spaces"> </code><code class="sql plain">s.id sid,</code>
</div>
<div class="line number3 index2 alt2">
<code class="sql spaces"> </code><code class="sql plain">s.</code><code class="sql keyword">name</code><code class="sql plain">,</code>
</div>
<div class="line number4 index3 alt1">
<code class="sql spaces"> </code><code class="sql plain">s.gender,</code>
</div>
<div class="line number5 index4 alt2">
<code class="sql spaces"> </code><code class="sql plain">s.score,</code>
</div>
<div class="line number6 index5 alt1">
<code class="sql spaces"> </code><code class="sql plain">c.id cid,</code>
</div>
<div class="line number7 index6 alt2">
<code class="sql spaces"> </code><code class="sql plain">c.</code><code class="sql keyword">name</code> <code class="sql plain">cname</code>
</div>
<div class="line number8 index7 alt1">
<code class="sql keyword">FROM</code> <code class="sql plain">students s, classes c;</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<p>
多表查询也是可以添加<code>WHERE</code>条件的。</p>
<p class="maodian">
</p>
<p class="maodian"></p><h2>
连接查询</h2>
<p>
连接查询是另一种类型的多表查询。连接查询对多个表进行JOIN运算,简单地说,就是先确定一个主表作为结果集,然后,把其他表的行有选择性地“连接”在主表结果集上。</p>
<p>
例如,我们想要选出<code>students</code>表的所有学生信息:</p>
<div class="jb51code">
<div>
<div class="syntaxhighlightersql" id="highlighter_47532">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="sql keyword">SELECT</code> <code class="sql plain">s.id, s.</code><code class="sql keyword">name</code><code class="sql plain">, s.class_id, s.gender, s.score </code><code class="sql keyword">FROM</code> <code class="sql plain">students s;</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<table>
<thead><tr>
<th>
id</th>
<th>
name</th>
<th>
class_id</th>
<th>
gender</th>
<th>
score</th>
</tr></thead>
<tbody>
<tr>
<td>
1</td>
<td>
小明</td>
<td>
1</td>
<td>
M</td>
<td>
90</td>
</tr>
<tr>
<td>
2</td>
<td>
小红</td>
<td>
1</td>
<td>
F</td>
<td>
95</td>
</tr>
<tr>
<td>
3</td>
<td>
小军</td>
<td>
1</td>
<td>
M</td>
<td>
88</td>
</tr>
<tr>
<td>
4</td>
<td>
小米</td>
<td>
1</td>
<td>
F</td>
<td>
73</td>
</tr>
<tr>
<td>
5</td>
<td>
小白</td>
<td>
2</td>
<td>
F</td>
<td>
81</td>
</tr>
<tr>
<td>
6</td>
<td>
小兵</td>
<td>
2</td>
<td>
M</td>
<td>
55</td>
</tr>
<tr>
<td>
7</td>
<td>
小林</td>
<td>
2</td>
<td>
M</td>
<td>
85</td>
</tr>
<tr>
<td>
8</td>
<td>
小新</td>
<td>
3</td>
<td>
F</td>
<td>
91</td>
</tr>
<tr>
<td>
9</td>
<td>
小王</td>
<td>
3</td>
<td>
M</td>
<td>
89</td>
</tr>
<tr>
<td>
10</td>
<td>
小丽</td>
<td>
3</td>
<td>
F</td>
<td>
88</td>
</tr>
</tbody>
</table>
<p>
但是,假设我们希望结果集同时包含所在班级的名称,上面的结果集只有<code>class_id</code>列,缺少对应班级的<code>name</code>列。</p>
<p>
现在问题来了,存放班级名称的<code>name</code>列存储在<code>classes</code>表中,只有根据<code>students</code>表的<code>class_id</code>,找到<code>classes</code>表对应的行,再取出<code>name</code>列,就可以获得班级名称。</p>
<p>
这时,连接查询就派上了用场。我们先使用最常用的一种内连接——INNER JOIN来实现:</p>
<div class="jb51code">
<div>
<div class="syntaxhighlightersql" id="highlighter_802628">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
<div class="line number2 index1 alt1">
2</div>
<div class="line number3 index2 alt2">
3</div>
<div class="line number4 index3 alt1">
4</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="sql keyword">SELECT</code> <code class="sql plain">s.id, s.</code><code class="sql keyword">name</code><code class="sql plain">, s.class_id, c.</code><code class="sql keyword">name</code> <code class="sql plain">class_name, s.gender, s.score</code>
</div>
<div class="line number2 index1 alt1">
<code class="sql keyword">FROM</code> <code class="sql plain">students s</code>
</div>
<div class="line number3 index2 alt2">
<code class="sql keyword">INNER</code> <code class="sql color1">JOIN</code> <code class="sql plain">classes c</code>
</div>
<div class="line number4 index3 alt1">
<code class="sql keyword">ON</code> <code class="sql plain">s.class_id = c.id;</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<table>
<thead><tr>
<th>
id</th>
<th>
name</th>
<th>
class_id</th>
<th>
class_name</th>
<th>
gender</th>
<th>
score</th>
</tr></thead>
<tbody>
<tr>
<td>
1</td>
<td>
小明</td>
<td>
1</td>
<td>
一班</td>
<td>
M</td>
<td>
90</td>
</tr>
<tr>
<td>
2</td>
<td>
小红</td>
<td>
1</td>
<td>
一班</td>
<td>
F</td>
<td>
95</td>
</tr>
<tr>
<td>
3</td>
<td>
小军</td>
<td>
1</td>
<td>
一班</td>
<td>
M</td>
<td>
88</td>
</tr>
<tr>
<td>
4</td>
<td>
小米</td>
<td>
1</td>
<td>
一班</td>
<td>
F</td>
<td>
73</td>
</tr>
<tr>
<td>
5</td>
<td>
小白</td>
<td>
2</td>
<td>
二班</td>
<td>
F</td>
<td>
81</td>
</tr>
<tr>
<td>
6</td>
<td>
小兵</td>
<td>
2</td>
<td>
二班</td>
<td>
M</td>
<td>
55</td>
</tr>
<tr>
<td>
7</td>
<td>
小林</td>
<td>
2</td>
<td>
二班</td>
<td>
M</td>
<td>
85</td>
</tr>
<tr>
<td>
8</td>
<td>
小新</td>
<td>
3</td>
<td>
三班</td>
<td>
F</td>
<td>
91</td>
</tr>
<tr>
<td>
9</td>
<td>
小王</td>
<td>
3</td>
<td>
三班</td>
<td>
M</td>
<td>
89</td>
</tr>
<tr>
<td>
10</td>
<td>
小丽</td>
<td>
3</td>
<td>
三班</td>
<td>
F</td>
<td>
88</td>
</tr>
</tbody>
</table>
<p>
注意INNER JOIN查询的写法是:</p>
<p>
先确定主表,仍然使用<code>FROM <表1></code>的语法;再确定需要连接的表,使用<code>INNER JOIN <表2></code>的语法;然后确定连接条件,使用<code>ON <条件...></code>,这里的条件是<code>s.class_id = c.id</code>,表示<code>students</code>表的<code>class_id</code>列与<code>classes</code>表的<code>id</code>列相同的行需要连接;可选:加上<code>WHERE</code>子句、<code>ORDER BY</code>等子句。</p>
<p>
有内连接(INNER JOIN)就有外连接(OUTER JOIN)</p>
<div class="jb51code">
<div>
<div class="syntaxhighlightersql" id="highlighter_656086">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
<div class="line number2 index1 alt1">
2</div>
<div class="line number3 index2 alt2">
3</div>
<div class="line number4 index3 alt1">
4</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="sql keyword">SELECT</code> <code class="sql plain">s.id, s.</code><code class="sql keyword">name</code><code class="sql plain">, s.class_id, c.</code><code class="sql keyword">name</code> <code class="sql plain">class_name, s.gender, s.score</code>
</div>
<div class="line number2 index1 alt1">
<code class="sql keyword">FROM</code> <code class="sql plain">students s</code>
</div>
<div class="line number3 index2 alt2">
<code class="sql color2">RIGHT</code> <code class="sql color1">OUTER</code> <code class="sql color1">JOIN</code> <code class="sql plain">classes c</code>
</div>
<div class="line number4 index3 alt1">
<code class="sql keyword">ON</code> <code class="sql plain">s.class_id = c.id;</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<table>
<thead><tr>
<th>
id</th>
<th>
name</th>
<th>
class_id</th>
<th>
class_name</th>
<th>
gender</th>
<th>
score</th>
</tr></thead>
<tbody>
<tr>
<td>
1</td>
<td>
小明</td>
<td>
1</td>
<td>
一班</td>
<td>
M</td>
<td>
90</td>
</tr>
<tr>
<td>
2</td>
<td>
小红</td>
<td>
1</td>
<td>
一班</td>
<td>
F</td>
<td>
95</td>
</tr>
<tr>
<td>
3</td>
<td>
小军</td>
<td>
1</td>
<td>
一班</td>
<td>
M</td>
<td>
88</td>
</tr>
<tr>
<td>
4</td>
<td>
小米</td>
<td>
1</td>
<td>
一班</td>
<td>
F</td>
<td>
73</td>
</tr>
<tr>
<td>
5</td>
<td>
小白</td>
<td>
2</td>
<td>
二班</td>
<td>
F</td>
<td>
81</td>
</tr>
<tr>
<td>
6</td>
<td>
小兵</td>
<td>
2</td>
<td>
二班</td>
<td>
M</td>
<td>
55</td>
</tr>
<tr>
<td>
7</td>
<td>
小林</td>
<td>
2</td>
<td>
二班</td>
<td>
M</td>
<td>
85</td>
</tr>
<tr>
<td>
8</td>
<td>
小新</td>
<td>
3</td>
<td>
三班</td>
<td>
F</td>
<td>
91</td>
</tr>
<tr>
<td>
9</td>
<td>
小王</td>
<td>
3</td>
<td>
三班</td>
<td>
M</td>
<td>
89</td>
</tr>
<tr>
<td>
10</td>
<td>
小丽</td>
<td>
3</td>
<td>
三班</td>
<td>
F</td>
<td>
88</td>
</tr>
<tr>
<td>
NULL</td>
<td>
NULL</td>
<td>
NULL</td>
<td>
四班</td>
<td>
NULL</td>
<td>
NULL</td>
</tr>
</tbody>
</table>
<p>
执行上述RIGHT OUTER JOIN可以看到,和INNER JOIN相比,RIGHT OUTER JOIN多了一行,多出来的一行是“四班”,但是,学生相关的列如<code>name</code>、<code>gender</code>、<code>score</code>都为<code>NULL</code>。</p>
<p>
这也容易理解,因为根据<code>ON</code>条件<code>s.class_id = c.id</code>,<code>classes</code>表的id=4的行正是“四班”,但是,<code>students</code>表中并不存在class_id=4的行。</p>
<p>
有RIGHT OUTER JOIN,就有LEFT OUTER JOIN,以及FULL OUTER JOIN。它们的区别是:</p>
<p>
INNER JOIN只返回同时存在于两张表的行数据,由于<code>students</code>表的<code>class_id</code>包含1,2,3,<code>classes</code>表的<code>id</code>包含1,2,3,4,所以,INNER JOIN根据条件<code>s.class_id = c.id</code>返回的结果集仅包含1,2,3。</p>
<p>
RIGHT OUTER JOIN返回右表都存在的行。</p>
<p>
如果某一行仅在右表存在,那么结果集就会以<code>NULL</code>填充剩下的字段。</p>
<p>
LEFT OUTER JOIN则返回左表都存在的行。</p>
<p>
如果我们给students表增加一列,并添加class_id=5,由于classes表并不存在id=5的列,所以,LEFT OUTER JOIN的结果会增加一列,对应的<code>class_name</code>是<code>NULL</code></p>
<p>
我们使用FULL OUTER JOIN,它会把两张表的所有记录全部选择出来,并且,自动把对方不存在的列填充为NULL</p>
<p class="maodian">
</p>
<p class="maodian"></p><h3>
小结</h3>
<p>
JOIN查询需要先确定主表,然后把另一个表的数据“附加”到结果集上;</p>
<blockquote>
<p>
INNER JOIN是最常用的一种JOIN查询,</p>
<p>
它的语法是SELECT ... FROM <表1> INNER JOIN <表2> ON <条件...>;</p>
</blockquote>
<p>
JOIN查询仍然可以使用<code>WHERE</code>条件和<code>ORDER BY</code>排序。</p>
<p>
以上就是SQL查询语法知识梳理总结的详细内容,更多关于SQL查询语法的资料请关注其它相关文章!</p>
<p>
原文链接:https://blog.csdn.net/weixin_38526306/article/details/87453772</p>
頁:
[1]