GVKun编程网logo

mysql之select语法

14

针对mysql之select语法这个问题,本篇文章进行了详细的解答,同时本文还将给你拓展7月2日总结,mysql之select_MySQL、mysqlselect语句执行顺序_MySQL、MySQLS

针对mysql之select语法这个问题,本篇文章进行了详细的解答,同时本文还将给你拓展7月2日总结,mysql 之select_MySQL、mysql select语句执行顺序_MySQL、MySQL SELECT语法(一)SELECT语法详解、MySQL SELECT语法(三)JOIN语法详解等相关知识,希望可以帮助到你。

本文目录一览:

mysql之select语法

mysql之select语法

一:连接查询(外链接outer和内链接inner)

  连接查询是另一种类型的多表查询。连接查询对多个表进行JOIN运算,简单地说,就是先确定一个主表作为结果集,然后,把其他表的行有选择性地“连接”在主表结果集上。

  语法:两个表的连接(left join table1 on 。。。 默认就是外链接即 left outer join table1 on 。。。)

  sql">

查询时 例如 SELECT * FROM classes c LEFT JOIN  teacher t  ON c.`id` = t.`class_id` ;

查询on后面符合条件的teacher表,

二班 二班 三班 四班

如何消除为null的数据(即使用外链接来达到内连接的效果)

classes c teacher t c.`id` t.`class_id` t.`class_id` classes c teacher t c.`id` t.`class_id` t.`class_id` classes c teacher t c.`id` t.`class_id`; (内连接)

对于连接查询有时我们比较容易混淆结果,一下是借鉴廖雪峰老师的图片来解释连接查询的结果,对我个人而言还是比较清晰的,希望对大家也有帮助

************************对于这么多种JOIN查询,到底什么使用应该用哪种呢?其实我们用图来表示结果集就一目了然了*******************。

此图是参考廖雪峰老师的教程,讲的很好https://www.liaoxuefeng.com/wiki/001508284671805d39d23243d884b8b99f440bfae87b0f4000/001509167103179399448cb200549bdab7651a5e9167597000

INNER JOIN  .....ON .....查询连个表的交集,默认会把 不符合条件的数据去除

************************************************************************外链接查询((left|right) [outer 默认参数 join table1 on condition)默认阐述就是outer   故我们常用的连接查询都是外链接查询****************

LEFT JOIN .....ON ....左连接查询(外链接),以左表为基表查询关联表,当主表中的数据没有和关联表中的数据对应时,主表后的字段会被null填充。

参考: RIGHT JOIN ....ON ....右连接查询。参考左连接查询

FULL OUTER JOIN则是选出左右表都存在的记录:(不知道为啥测试不生效)

二 :连接查询中的交叉(CROSS)查询

  语法: 如果table_reference)项目列表中的每个逗号被视为等同于内部联接

t1 (t2.a t1.a t3.b t1.b t4.c 相当于(把,换成了CROSS JOIN )
<span>SELECT <span>* <span>FROM t1 <span>LEFT <span>JOIN (t2 <span>CROSS <span>JOIN t3 <span>CROSS <span>JOIN<span> t4)
<span>ON (t2.a <span>= t1.a <span>AND t3.b <span>= t1.b <span>AND t4.c <span>= t1.c)

例如sql:交叉查询

   SELECT * FROM classes c LEFT JOIN ( teacher t,students s ) ON c.`id` = s.`class_id` AND c.`id` = t.`class_id`;  ()

结果:

类比sql :(左外连接查询)

    SELECT * FROM classes c LEFT JOIN  teacher t ON c.`id`=t.`class_id` LEFT JOIN students s ON c.`id`=s.`class_id`;

结果:

通过对比左外查询3个表的内容我分析如下

交叉查询:是先以主表为基表(from 后的表),查询join 后的多表根据on 后面的条件,若on后的条件全部成立才显示后面表的内容,若有不成立的则不显示。

     基表后不满足条件的数据,则填充为null

注意与多表联合的差别

备注:

teral">  1.JOIN优先级高于逗号运算符(teral">,),因此连接表达式 teral">t1,t2 JOIN t3被解释为 teral">(t1,(t2 JOIN t3)),而不是teral">((t1,t2) JOIN t3)这会影响使用teral">ON子句的语句, 因为该子句只能引用连接操作数中的列,并且优先级会影响对这些操作数的解释。

7月2日总结,mysql 之select_MySQL

7月2日总结,mysql 之select_MySQL

函数:

MAX(); 返回该字段的最大值  

MIN();返回该字段的最小值

COUNT(); 

返回该数据库的行数切非NULL的值,count(*)返回该数据库里的行数,count(name),如果是字段值,若该字段的值有NULL的情况,则该不计入总数。

AVG();返回该字段的平均值

SUM();返回该字段的总和

GROUP BY: 对所在字段进行分组。

若数据库里有张三,李四,王五,张三,赵六,李四

select * from name where 1 group by name, 该字段就是输出后,张三,李四,王五,赵六.(李四和张三有多条,也各显示纪录)

ORDER BY: 对字段进行升序/降序 进行排列;

DESC 降序          ASC 升序

     select * from goods ordery by  id desc  对id列进行降序排序

LIMIT限制条目  LIMIT[Offset,] N     offset是偏移量(可选项) N取出的条目

   select * from goods order by id desc limit 0,3 对id进行从大到小排序,只显示前三条纪录。

select * from goods order by id desc limit 2,3 对id进行从大到小排序,只显示3,4,5条纪录;

   

mysql select语句执行顺序_MySQL

mysql select语句执行顺序_MySQL

bitsCN.com

SELECT语句定义
      一个完成的SELECT语句包含可选的几个子句。SELECT语句的定义如下:

SELECT语句执行顺序
      SELECT语句中子句的执行顺序与SELECT语句中子句的输入顺序是不一样的,所以并不是从SELECT子句开始执行的,而是按照下面的顺序执行:
      开始->FROM子句->WHERE子句->GROUP BY子句->HAVING子句->ORDER BY子句->SELECT子句->LIMIT子句->最终结果
      每个子句执行后都会产生一个中间结果,供接下来的子句使用,如果不存在某个子句,就跳过

bitsCN.com

MySQL SELECT语法(一)SELECT语法详解

MySQL SELECT语法(一)SELECT语法详解

  源自MySQL 5.7 官方手册:13.2.9 SELECT Syntax

  SELECT的语法如下:

SELECT
    [ALL | DISTINCT | DISTINCTROW ]
      [HIGH_PRIORITY]
      [STRAIGHT_JOIN]
      [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
      [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
    select_expr [, select_expr ...]
    [FROM table_references
      [PARTITION partition_list]
    [WHERE where_condition]
    [GROUP BY {col_name | expr | position}
      [ASC | DESC], ... [WITH ROLLUP]]
    [HAVING where_condition]
    [ORDER BY {col_name | expr | position}
      [ASC | DESC], ...]
    [LIMIT {[offset,] row_count | row_count OFFSET offset}]
    [PROCEDURE procedure_name(argument_list)]
    [INTO OUTFILE ''file_name''
        [CHARACTER SET charset_name]
        export_options
      | INTO DUMPFILE ''file_name''
      | INTO var_name [, var_name]]
    [FOR UPDATE | LOCK IN SHARE MODE]]

 一、SELECT解析

  SELECT用于从一个或者多个表中取回数据行,也可以包括UNION语句和子查询。UNION语句参考后续文章,而子查询在手册13.2.10节。

  SELECT语句最常用的子句有这些:

  SELECT也可用于检索计算的行而不引用任何表。

mysql> SELECT 1 + 1;
        -> 2

  在没有引用表的情况下,允许将DUAL指定为虚拟表名:

mysql> SELECT 1 + 1 FROM DUAL;
        -> 2

  DUAL的存在只是为了方便。MySQL可能会忽略这些子句。如果没有引用表,MySQL不需要FROM DUAL。

 

  通常,使用的子句必须完全按照语法描述中展示的顺序给出。

  例如,HAVING子句必须位于任何GROUP BY子句之后和任何ORDER BY子句之前。例外情况是INTO子句可以如语法描述中所示出现,也可以紧跟在select_expr列表之后出现。SELECT...INTO后续文章会讲。

  

  select_expr项列表包括了要取回的列,该项可以指定一个字段、一个表达式或者使用*号。

 

二、关于SELECT子句的一些附加知识:

  2.1

  可以使用AS alias_name为select_expr指定别名。别名用作表达式的列名,可用于GROUP BY,ORDER BY或HAVING子句。

  AS关键字是可选项,在指定列的别名时养成使用AS是一种好习惯。

  MySQL不允许在WHERE子句中引用列的别名,因为当WHERE子句执行时,列值可能还尚未确定。See Section B.4.4.4, “Problems with Column Aliases”.

  2.2

  FROM后的table_references指示参与查询的一个或者多个表。如果列出了多个表,就会执行JOIN操作。而对于每一个指定表,都可以为其定义别名。

tbl_name [[AS] alias] [index_hint]

  使用index_hint,会为优化器提供有关如何在查询处理期间选择索引的信息。关于它,see Section 8.9.4, “Index Hints”。

  当然,也可以使用SET max_seeks_for_key = value作为替代方法,强制MySQL更优先使用键扫描而不是表扫描。See Section 5.1.7, “Server System Variables”

  2.3

  不使用AS也能为表定义别名,直接空格后填写即可。

  2.4

  SELECT后被选择的列,可以在ORDER IN和GROUP BY中,通过列名、列别名或者代表列位置的整数(从1开始)来引用:

SELECT college, region, seed FROM tournament
  ORDER BY region, seed;

SELECT college, region AS r, seed AS s FROM tournament
  ORDER BY r, s;

SELECT college, region, seed FROM tournament
  ORDER BY 2, 3;

  如果ORDER BY出现在子查询中,并且也应用于外部查询,则最外层的ORDER BY优先。

  例如,以下语句的结果按降序排序,而不是按升序排序:

(SELECT ... ORDER BY a) ORDER BY a DESC;

  不推荐使用代表列位置的数字的方法,因为这已经从标准SQL中删除。

  2.5

  如果使用了GROUP BY,被分组的列会自动按升序排列(就好像有一个ORDER BY语句后面跟了同样的列)。如果要避免GROUP BY因为自动排序生成的开销,添加ORDER BY NULL可以解决:

SELECT a, COUNT(b) FROM test_table GROUP BY a ORDER BY NULL;

  虽然在GROUP BY语句上也有一些对字段指定排序的用法,但是他们现在都已经被抛弃。正确的做法是,使用ORDER BY子句来进行排序。

  2.6

  当使用ORDER BY或GROUP BY对SELECT中的列进行排序时,服务器仅使用max_sort_length系统变量指示的初始字节数对值进行排序。

  2.7

  MySQL扩展了GROUP BY的用法,它允许在Select列表中出现没有在GROUP BY中进行分组的字段。这点在前面的聚合函数的文章中已经讲得很清楚。

  2.8

  GROUP BY子句允许添加WITH ROLLUP修饰符

  2.9

  Having子句一般应用在最后,恰好在结果集被返回给MySQL客户端前,且没有进行优化。(而LIMIT应用在HAVING后)

  SQL标准要求:HAVING必须引用在GROUP BY列表中或者聚合函数使用的列。然而,MySQL对此进行了扩展,它允许HAVING引用Select子句列表中的列,还有外部子查询的列。

  如果HAVING引用的列具有歧义,会有警告产生。下面的语句中,col2具有歧义:

SELECT COUNT(col1) AS col2 FROM t GROUP BY col2 HAVING col2 = 2;

  这里没报错只有警告是为什么呢?因为MySQLS虽然对标准SQL进行了扩展,但是在这种情况下,标准SQL的选择具有优先权。即MySQL把HAVING中的col2优先指向GROUP BY中的col2。

  2.11

  切记不要在该使用WHERE的地方使用HAVING。HAVING是和GROUP BY搭配的。

  2.12

  HAVING子句可以引用聚合函数,而WHERE不能。

SELECT user, MAX(salary) FROM users
  GROUP BY user HAVING MAX(salary) > 10;

  上面的查询在老版本的MySQL可能无效。

  2.13

  MySQL允许重复的列名。也就是说,同名的select_expr可以有多个。这是对标准SQL的扩展。而因为MySQL允许GROUP BY和HAVING引用select_expr值,这可能会引起歧义:

SELECT 12 AS a, a FROM t GROUP BY a;

  在这个语句中,两个列都名为a(实际应该是不同)。(着应该是被允许的)

  那么为了不引起歧义以对正确的列进行分组,切记对select_expr使用不同的别名。

  2.14

  对于ORDER BY子句中的非限定列或别名引用,MySQL是这样进行解析的:先搜索SELECT子句列表中的select_expr值,然后在FROM后的表中的列。

  而对于GROUP BY和HAVING子句中的非限定列或别名,MySQL先搜索FROM子句,再搜索SELECT子句。

  2.15

  LIMIT子句可用于约束SELECT语句返回的行数。

  LIMIT可以有一个或者两个参数,都必须为非负整数。

  但是也有例外情况:

  若LIMIT有两个参数,第一个指定相对于第一行的偏移量,第二个参数指定应该返回的行数。第一行自己的偏移量是0,而不是1:

/*取回结果集中的6~15行*/
SELECT * FROM tbl LIMIT 5,10;

  那如果要取回一个设定某个偏移量之后的所有行,可以为第二参数设定一个非常大的常量。以下查询取回从第96行起的所有数据:

SELECT * FROM tbl LIMIT 95,18446744073709551615;

  若LIMIT只有一个参数,则参数指定应该取回的行数,偏移量默认为0,即从第一行起。

 

  对于预编译SQL语句,可以使用占位符:

/*取回第一行数据*/
SET @a=1;
PREPARE STMT FROM ''SELECT * FROM tbl LIMIT ?'';
EXECUTE STMT USING @a;

/*取回第2~6行数据*/
SET @skip=1; 
SET @numrows=5; 
PREPARE STMT FROM ''SELECT * FROM tbl LIMIT ?, ?''; 
EXECUTE STMT USING @skip, @numrows;

  为了与PostgreSQL兼容,MySQL还支持LIMIT row_count OFFSET offset 的语法。

  如果子查询中有LIMIT,而外部的查询同样有LIMIT,此时最外层查询的LIMIT优先。例如,以下语句返回的行应该是2条,而不是1条:

(SELECT ... LIMIT 1) LIMIT 2;

 

  2.16

  PROCEDURE子句命名了一个对结果集进行处理的存储过程。Section 8.4.2.4, “Using PROCEDURE ANALYSE” 这一节,描述了ANALYSE关键字的使用。一个存储过程,可用于获取有助于减少表大小的最佳列数据类型的建议。(点进去才发现从MySQL 5.7.18开始,PROCEDURE ANALYZE()已被弃用,并在MySQL 8.0中被删除。)

  2.17

  SELECT...INTO可以让查询结果写入到文件或者保存到变量中,后续的文章会讲这个。

  2.18

  如果使用在一个使用了页级锁或者行级锁的存储引擎中使用FOR UPDATE,被某个查询所检查的行将会处于“写锁定”中,直到当前事务结束。使用LOCK IN SHARE MODE设置共享锁,允许其他事务读取已检查的行,但不允许更新或删除它们。See Section 14.7.2.4, “Locking Reads”.

  此外,你不能在下面的语句中将FOR UPDATE作为SELECT查询的一部分:

CREATE TABLE new_table SELECT ... FROM old_table ....

  如果尝试这么做,该语句会被拒绝,并报错——Can''t update table ''old_table'' while ''new_table'' is being created。在MySQL 5.5以及更早的版本中有所不同。(This is a change in behavior from MySQL 5.5 and earlier, which permitted CREATE TABLE ... SELECT statements to make changes in tables other than the table being created.)

 

三、SELECT关键字的修饰符

  紧跟SELECT关键字,你可以使用一些列修饰符,来影响语句的操作。

  HIGH_PRIORITY,STRAIGHT_JOIN和以SQL_开头的修饰符是标准SQL的MySQL扩展。

  3.1

  ALL和DISTINCT修饰符指定是否对结果集中的行(应该不是某个列)去重。

  ALL是默认修饰符,即满足要求的所有行都要被取回来。

  DISTINCT删除重复的行。

  3.2

  HIGH_PRIORITY修饰符会让SELECT语句比更改表(这里英文用得是update,不晓得是更新还是更改)的语句有更高的优先级。

  这个修饰符只应该在非常快且能被立即执行的查询当中使用。

  在表被锁定以进行读取时发出的SELECT HIGH_PRIORITY查询也会运行,即使有一个更新语句正在等待表被释放。这仅影响仅使用表级锁定的存储引擎(例如MyISAM,MEMORY和MERGE)。

  HIGH_PRIORITY不能与属于UNION的SELECT语句一起使用。

  3.3

  STRAIGHT_JOIN强制优化器按照FROM子句中列出的顺序连接表。如果优化程序以非最佳顺序连接表,则可以使用此方法加速查询.STRAIGHT_JOIN也可以在table_references列表中使用。JOIN语法中会讲到。

  STRAIGHT_JOIN不适用于被优化器视为const或system的任何表。这种表只产生一行数据,在查询执行的优化阶段读取,并且在查询执行进行之前用适当的列值替换对其列的引用。这些表将首先出现在EXPLAIN显示的查询计划中。See Section 8.8.1, “Optimizing Queries with EXPLAIN”.

  This exception may not apply to const or system tables that are used on the NULL-complemented side of an outer join (that is, the right-side table of a LEFT JOIN or the left-side table of a RIGHT JOIN.

 

  3.4

  SQL_BIG_RESULT或SQL_SMALL_RESULT可以与GROUP BY或DISTINCT一起使用,分别告诉优化器结果集有很多行或者很小。

  对于SQL_BIG_RESULT,MySQL直接使用基于磁盘的临时表(如果已创建),并且更偏向使用在GROUP BY中元素的key的临时表来进行排序。

  对于SQL_SMALL_RESULT,MySQL使用内存中的临时表来存储生成的表而不是使用排序。通常不需要这样做。

  3.5

  SQL_BUFFER_RESULT强制将结果放入临时表中.

  这有助于MySQL尽早释放表锁,在需要很长时间将结果集发送到客户端的情况下,这样也更好。

  此修饰符只能用于顶级SELECT语句,不能用于子查询或UNION之后。

  3.6

  SQL_CALC_FOUND_ROWS告诉MySQL计算结果集中将有多少行,忽略任何LIMIT子句。

  然后可以使用SELECT FOUND_ROWS()检索行数。See Section 12.15, “Information Functions”.

  这个参数就是为了方便统计在不使用LIMIT时的结果集。

 

  3.7

  SQL_CACHE和SQL_NO_CACHE修饰符会影响查询缓存中查询结果的缓存。(see Section 8.10.3, “The MySQL Query Cache”)

  SQL_CACHE告诉MySQL将结果存储在查询缓存中(如果它是可缓存的,并且query_cache_type系统变量的值是2或DEMAND)。

  使用SQL_NO_CACHE,服务器不使用查询缓存。它既不检查查询缓存,也不检查结果是否已缓存,也不缓存查询结果。

  这两个修饰符是互斥的,如果同时指定它们则会发生错误。

  此外,子查询(包括FROM子句中的子查询)和第一个SELECT以外的UNION中的SELECT语句不允许使用这些修饰符。

  对于视图,如果SQL_NO_CACHE出现在查询中的任何SELECT中,则适用

  For a cacheable query, SQL_CACHE applies if it appears in the first SELECT of a view referred to by the query.

  从MySQL 5.7.20开始,不推荐使用查询缓存,并在MySQL 8.0中删除。弃用包括SQL_CACHE和SQL_NO_CACHE。

 

  最后还有一个关于对分表查询时锁定情况因存储引擎不同而不同的段落。

 

 

 

With SQL_NO_CACHE, the server does not use the query cache. It neither checks the query cache to see whether the result is already cached, nor does it cache the query result.

MySQL SELECT语法(三)JOIN语法详解

MySQL SELECT语法(三)JOIN语法详解

  源自MySQL 5.7 官方手册:13.2.9.2 JOIN Syntax

SELECT select_expr
From table_references JOIN...
WHERE...

  如上所示,MySQL支持在table_references后添加JOIN选项作为SELECT语句的一部分,当然也可以在多表的DELETE和UPDATE。

  下面列出了JOIN的详细语法:

table_references:
    escaped_table_reference [, escaped_table_reference] ...

escaped_table_reference:
    table_reference
  | { OJ table_reference }

table_reference:
    table_factor
  | joined_table

table_factor:
    tbl_name [PARTITION (partition_names)]
        [[AS] alias] [index_hint_list]
  | table_subquery [AS] alias
  | ( table_references )

joined_table:
    table_reference [INNER | CROSS] JOIN table_factor [join_specification]
  | table_reference STRAIGHT_JOIN table_factor
  | table_reference STRAIGHT_JOIN table_factor ON search_condition
  | table_reference {LEFT|RIGHT} [OUTER] JOIN table_reference join_specification
  | table_reference NATURAL [{LEFT|RIGHT} [OUTER]] JOIN table_factor

join_specification:
    ON search_condition
  | USING (join_column_list)

join_column_list:
    column_name [, column_name] ...

index_hint_list:
    index_hint [, index_hint] ...

index_hint:
    USE {INDEX|KEY}
      [FOR {JOIN|ORDER BY|GROUP BY}] ([index_list])
  | {IGNORE|FORCE} {INDEX|KEY}
      [FOR {JOIN|ORDER BY|GROUP BY}] (index_list)

index_list:
    index_name [, index_name] ...

 

一、表引用(table reference)

  一个表引用也被称为一个JOIN表达式。表引用(当它引用分区表时)可能有PARTITION选项,包括一个由逗号分隔的分区,子分区或两者皆有的列表。此选项紧跟在的名字之后,并在任何别名声明之前。此选项的作用是仅从列出的分区或子分区中选择数据行,而且将忽略列表中未命名的任何分区或子分区。see Section 22.5, “Partition Selection”。

  table_factor语法是MySQL对标准SQL中的扩展。标准SQL只接受table_reference,而不是一对括号内的列表。

  如果table_reference项列表中的每个逗号被视为内连接(INNER JOIN),则这是保守的扩展。例如:

SELECT * FROM t1 LEFT JOIN (t2, t3, t4)
                 ON (t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)

等价于:

SELECT * FROM t1 LEFT JOIN (t2 CROSS JOIN t3 CROSS JOIN t4)
                 ON (t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)

在MySQL中,JOIN,CROSS JOIN,和INNER JOIN 在语义上是等价的,他们可以相互替换。但是在标准SQL中,他们不等价,INNER JOIN与ON搭配使用,CROSS JOIN搭配其它。

  一般来说,在只有INNER JOIN操作的表达式中,括号可以被省略。MySQL还支持嵌套连接,

See Section 8.2.1.7, “Nested Join Optimization”。

 

  指定索引提示(Index  hints )能够影响MySQL优化器如何使用索引。更多信息,see Section 8.9.4, “Index Hints”.

  优化器提示和optimizer_switch系统变量是影响优化器使用索引的其他方法。See Section 8.9.3, “Optimizer Hints”, and Section 8.9.2, “Switchable Optimizations”。

 

二、在编写联接时要考虑的一般因素

  2.1 

  可以使用tbl_name AS alias_name或tbl_name alias_name对表引用定义别名。

SELECT t1.name, t2.salary
  FROM employee AS t1 INNER JOIN info AS t2 ON t1.name = t2.name;

SELECT t1.name, t2.salary
  FROM employee t1 INNER JOIN info t2 ON t1.name = t2.name;

  2.2 

  table_subquery也称为FROM子句中的派生表或子查询。Section 13.2.10.8, “Derived Tables”. 

  此类子查询必须包含别名,以便为子查询结果提供表名。一个简单的例子如下:

SELECT * FROM (SELECT 1, 2, 3) AS t1;

/*

+---+---+---+
| 1 | 2 | 3 |
+---+---+---+
| 1 | 2 | 3 |
+---+---+---+

*/

  2.3

  在没有连接条件的情况下,INNER JOIN和“,”(逗号)在语义上是等效的——两者都在指定的表之间产生笛卡尔积,也就是说,第一个表中的每一行都连接到第二个表中的每一行。

  但是,逗号运算符的优先级比其它含有“JOIN”的运算符要小。如果在存在连接条件时将逗号连接与其他连接类型混合,则可能会报错:Unknown column ''col_name'' in ''on clause'' 。对这个问题的处理会在文章的后面讨论。

  与ON一起使用的search_condition是可以在WHERE子句中使用的任何条件表达式。ON子句用于指明如多表如何连接,WHERE子句则限制要包含在结果集中的行。

 

  2.4

  在LEFT JOIN中,如果在右表中没有匹配ON或者USING中条件的行,则该连接中中的右表的列全都设置为NULL。你可以利用这点来查找左表A中在右表B中没有任何对应项的行:

SELECT left_tbl.*
  FROM left_tbl LEFT JOIN right_tbl ON left_tbl.id = right_tbl.id
  WHERE right_tbl.id IS NULL;

  这个查询语句会找出左表left_tbl中这样的行:其ID值在右表right_tbl的ID列中不存在。See Section 8.2.1.8, “Outer Join Optimization”.(外连接包括LEFT JOIN和RIGHT JOIN)

  例如,我查找学生表stu中在成绩表sc中没有任何成绩的学生:

select stu.* 
from student as stu left join sc on stu.SId=sc.SId
where sc.SId is null; /* SId | Sname | Sage | Ssex | +------+-------+---------------------+------+ | 09 | 张三 | 2017-12-20 00:00:00 | 女 | | 10 | 李四 | 2017-12-25 00:00:00 | 女 | | 11 | 李四 | 2017-12-30 00:00:00 | 女 | | 12 | 赵六 | 2017-01-01 00:00:00 | 女 | | 13 | 孙七 | 2018-01-01 00:00:00 | 女 | +------+-------+---------------------+------+ */

  当然这里碰到了一个小问题,把查询语句的WHERE条件改成sc.SId=null时,取出的是空集:

select stu.* 
from student as stu left join sc on stu.SId=sc.SId 
where sc.SId=null;

/*

Empty set (0.08 sec)

*/

  在WHERE子句中,column = null永远不会为true,以这种方式使用null无效,要检测值为NULL的列,必须使用IS NULL或列IS NOT NULL。关于NULL的使用有专门的章节:Working with NULL Values。

 

  2.5 

  USING(join_column_list)子句指定两个表中必须拥有的列的列表。如果表a和b都包含列c1,c2和c3,则以下连接将比较两个表中的相应列:

a LEFT JOIN b USING (c1, c2, c3)

  2.6 

  两个表的NATURAL [LEFT] JOIN等下于下面的情况:带有USING子句的INNER JOIN或LEFT JOIN,该子句列出了在两个表中都存在的所有的列。

  2.7

  RIGHT JOIN的工作方式类似于LEFT JOIN。为了使代码可以跨数据库移植,建议您使用LEFT JOIN而不是RIGHT JOIN。

  2.8

  语法描述中的{ OJ...},只是为了兼容ODBC。这个花括号必须按字面编写。

SELECT left_tbl.*
    FROM { OJ left_tbl LEFT OUTER JOIN right_tbl
           ON left_tbl.id = right_tbl.id }
    WHERE right_tbl.id IS NULL;

  您可以在{OJ ...}中使用其他类型的连接,例如INNER JOIN或RIGHT OUTER JOIN。这有助于与某些第三方应用程序兼容,但不是官方ODBC语法。

 

  2.9

  STRAIGHT_JOIN类似于JOIN,只是左表始终在右表之前读取。

  这可以用于连接优化器以次优顺序处理表的那些(少数)情况。 

  一些JOIN示例:

SELECT * FROM table1, table2;

SELECT * FROM table1 INNER JOIN table2 ON table1.id = table2.id;

SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id;

SELECT * FROM table1 LEFT JOIN table2 USING (id);

SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
  LEFT JOIN table3 ON table2.id = table3.id;

  Natural join和使用USING的JOIN,包括外连接的变体,是根据SQL-2003的标准进行处理的。

  

  2.10

  NATURAL连接中的冗余列不会显示。

CREATE TABLE t1 (i INT, j INT);
CREATE TABLE t2 (k INT, j INT);
INSERT INTO t1 VALUES(1, 1);
INSERT INTO t2 VALUES(1, 1);
SELECT * FROM t1 NATURAL JOIN t2;
SELECT * FROM t1 JOIN t2 USING (j);

  第一个和第二个SELECT语句中的“j”列,都只会出现一次:

/*

+------+------+------+
| j    | i    | k    |
+------+------+------+
|    1 |    1 |    1 |
+------+------+------+

+------+------+------+
| j    | i    | k    |
+------+------+------+
|    1 |    1 |    1 |
+------+------+------+

*/

  冗余列的消除和列的排序都是根据标准SQL进行处理,按下面的顺序展示:

  取代两个表的相同列的单列是通过使用coalesce(合并)操作来定义的,也就是说,对于两个t1.a和t2.a,得到的单个连接列a被定义为a = COALESCE(t1.a,t2.a):

COALESCE(x, y) = (CASE WHEN x IS NOT NULL THEN x ELSE y END)

  

  如果任何其他的join操作,则连接的结果列由参与连接的表的所有列的串联组成。合并的列的定义结果是,对于外连接,如果两列中的一列始终为NULL,则合并列包含非NULL列的值。如果两列都不为NULL或者都为NULL,两个公共列具有相同的值,因此选择哪一列作为合并列的值就无关紧要了。解释这一点的一种简单方法是考虑外连接的合并列由JOIN的内部表的公共列表示。

  假设表t1(a,b)和t2(a,c)具有以下内容:

/*

t1    t2
----  ----
1 x   2 z
2 y   3 w

*/

  那么下面这个JOIN,列a包含的是t1.a的值:

SELECT * FROM t1 NATURAL LEFT JOIN t2;

+------+------+------+
| a    | b    | c    |
+------+------+------+
|    1 | x    | NULL |
|    2 | y    | z    |
+------+------+------+

 

  而下面的JOIN,恰好相反,a列包含的是t2.a的值:

SELECT * FROM t1 NATURAL RIGHT JOIN t2;
+------+------+------+ | a | c | b | +------+------+------+ | 2 | z | y | | 3 | w | NULL | +------+------+------+

  将这些结果与JOIN ... ON的等效查询进行比较:

SELECT * FROM t1 LEFT JOIN t2 ON (t1.a = t2.a);

+------+------+------+------+
| a    | b    | a    | c    |
+------+------+------+------+
|    1 | x    | NULL | NULL |
|    2 | y    |    2 | z    |
+------+------+------+------+
SELECT * FROM t1 RIGHT JOIN t2 ON (t1.a = t2.a);

+------+------+------+------+
| a    | b    | a    | c    |
+------+------+------+------+
|    2 | y    |    2 | z    |
| NULL | NULL |    3 | w    |
+------+------+------+------+

 

  2.11

  USING子句可以使用ON子句进行重写。尽管他们两个很像,但还是有所不同。

  看下下面两个查询:

a LEFT JOIN b USING (c1, c2, c3)
a LEFT JOIN b ON a.c1 = b.c1 AND a.c2 = b.c2 AND a.c3 = b.c3

  在筛选条件上,这两个连接在语义上是一致的。但是在“要为SELECT *扩展显示哪些列”上,这两个连接在语义上并不相同。USING连接选择相应列的合并值,而ON连接选择所有表中的所有列。

  对使用USING的JOIN,SELECT *选择这些值:

COALESCE(a.c1, b.c1), COALESCE(a.c2, b.c2), COALESCE(a.c3, b.c3)

  而使用ON的JOIN,SELECT *选择如下:

a.c1, a.c2, a.c3, b.c1, b.c2, b.c3

  对于内连接,COALESCE(a.c1,b.c1)与a.c1或b.c1相同,因为两列的值都相同。

  对于外连接(例如LEFT JOIN),两列中的一列可以为NULL。该列会从结果中略去。

 

  2.12

  ON子句只能引用其操作范围内的操作数。

CREATE TABLE t1 (i1 INT);
CREATE TABLE t2 (i2 INT);
CREATE TABLE t3 (i3 INT);

SELECT * FROM t1 JOIN t2 ON (i1 = i3) JOIN t3;

  执这个SELECT语句会报错:Unknown column ''i3'' in ''on clause'' ,因为i3是t3中的一列,它不是ON子句的操作数。

  对此语句进行修改:

SELECT * FROM t1 JOIN t2 JOIN t3 ON (i1 = i3);

  对ON的作用范围进行测试,以下语句均能执行:

SELECT * FROM t1 JOIN t2 JOIN t3 ON (i2 = i3);
Empty set (0.00 sec)

SELECT * FROM t1 JOIN t2 JOIN t3 ON (i1 = i2);
Empty set (0.00 sec)

  即ON对其之前的JOIN中的表的列都能引用。

 

  2.13

  JOIN比逗号操作符拥有更高的优先级,所以下面这个表达式:

t1, t2 JOIN t3

  会被解释为:

(t1, (t2 JOIN t3))

  而不是:

((t1, t2) JOIN t3)

  这个特点会影响使用ON子句的语句,因为ON子句只能引用JOIN操作的表中的列,优先级会影响对这些操作表的解释。执行如下的语句就报错了:

SELECT * FROM t1,t2 JOIN t3 ON (i1 = i2);

ERROR 1054 (42S22): Unknown column ''i1'' in ''on clause''

  而这样就能成功执行:

SELECT * FROM (t1,t2) JOIN t3 ON (i1 = i2);

Empty set (0.00 sec)

  或者不适用逗号:

SELECT * FROM t1 join t2 JOIN t3 ON (i1 = i2);

Empty set (0.00 sec)

  此外,INNER JOIN,CROSS JOIN,LEFT JOIN和RIGHT JOIN混合的语句中,所有这些语句的优先级都高于逗号运算符。

 

  2.14

  与SQL:2003标准相比,MySQL扩展是MySQL允许您限定NATURAL或USING连接的公共(coalesced合并)列,而标准SQL不允许这样做。

 

我们今天的关于mysql之select语法的分享就到这里,谢谢您的阅读,如果想了解更多关于7月2日总结,mysql 之select_MySQL、mysql select语句执行顺序_MySQL、MySQL SELECT语法(一)SELECT语法详解、MySQL SELECT语法(三)JOIN语法详解的相关信息,可以在本站进行搜索。

本文标签:

上一篇mysql之UPDATE,SELECT,INSERT语法

下一篇sql之left join、right join、inner join的区别(数据库中inner join和left join的区别)