MySQL语句笔记

  • 更新时间:
  • 2213人关注
  • 点击下载

这是一个不错的MySQL笔记类学习资源,由怀靖雁提供,主要知识点是关于MySQL语句、MySQL笔记、MySQL、MySQL笔记的内容,已被125人关注,同类资源中评分为8.2分。

资源详情相关推荐
  • 大小:1.9 MB
  • 类别:MySQL笔记
  • 格式:PDF
  • 编辑:欧虹玉
  • 热度:878
  • PHP和MySQL Web开发(第4版)
  • MySQL王者晋级之路
  • MySQL入门经典
  • 深入浅出MySQL使用手册
  • MySQL从入门到项目实践
  • 精选笔记:MySQL中无GROUP BY情况下直接使用HAVING语句的问题探究

    2小时12分钟前回答

    今天有同学给我反应,有一张表,id是主键,这样的写法可以返回一条记录:

      “SELECT * FROM t HAVING id=MIN(id);”
    
    

       但是只是把MIN换成MAX,这样返回就是空了:

      “SELECT * FROM t HAVING id=MAX(id);”
    
    

       这是为什么呢?

       我们先来做个试验,验证这种情况。

       这是表结构,初始化两条记录,然后试验:

    root@localhost : plx 10:25:10> show create table t2G
    *************************** 1. row ***************************
        Table: t2
    Create Table: CREATE TABLE `t2` (
     `a` int(11) DEFAULT NULL,
     `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
     PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
     
    root@localhost : plx 10:25:15> select * from t2;
    +------+----+
    | a  | id |
    +------+----+
    |  1 | 1 |
    |  1 | 3 |
    +------+----+
    2 rows in set (0.00 sec)
     
    root@localhost : plx 10:25:20> SELECT * FROM t2 HAVING id=MIN(id);
    +------+----+
    | a  | id |
    +------+----+
    |  1 | 1 |
    +------+----+
    1 row in set (0.00 sec)
     
    root@localhost : plx 10:25:30> SELECT * FROM t2 HAVING id=MAX(id);
    Empty set (0.00 sec)
    
    

       初看之下,好像真的是这样哎,怎么会这样呢?

       我再试一下,把a字段改一个为10,然后试下a字段:

    root@localhost : plx 10:26:58> select * from t2;
    +------+----+
    | a  | id |
    +------+----+
    |  10 | 1 |
    |  1 | 3 |
    +------+----+
    2 rows in set (0.00 sec)
     
    root@localhost : plx 10:28:20> SELECT * FROM t2 HAVING a=MAX(a);
    +------+----+
    | a  | id |
    +------+----+
    |  10 | 1 |
    +------+----+
    1 row in set (0.00 sec)
     
    root@localhost : plx 10:28:28> SELECT * FROM t2 HAVING a=MIN(a);
    Empty set (0.00 sec)
    
    

       我擦,这回MAX能返回,MIN不能了,这又是为啥呢?

       旁白

       一般来说,HAVING子句是配合GROUP BY使用的,单独使用HAVING本身是不符合规范的,

       但是MySQL会做一个重写,加上一个GROUP BY NULL,”SELECT * FROM t HAVING id=MIN(id)”会被重写为”SELECT * FROM t GROUP BY NULL HAVING id=MIN(id)”,这样语法就符合规范了。

       继续……

       但是,这个 GROUP BY NULL 会产生什么结果呢?经过查看代码和试验,可以证明,GROUP BY NULL 等价于 LIMIT 1:

    root@localhost : plx 10:25:48> SELECT * FROM t2 GROUP BY NULL;
    +------+----+
    | a  | id |
    +------+----+
    |  10 | 1 |
    +------+----+
    1 row in set (0.00 sec)
    
    

       也就是说,GROUP BY NULL 以后,只会有一个分组,里面就是第一行数据。

       但是如果这样,MIN、MAX结果应该是一致的,那也不应该MAX和MIN一个有结果,一个没结果啊,这是为什么呢,再做一个测试。

       修改一下数据,然后直接查看MIN/MAX的值:

    root@localhost : plx 10:26:58> select * from t2;
    +------+----+
    | a  | id |
    +------+----+
    |  10 | 1 |
    |  1 | 3 |
    +------+----+
    2 rows in set (0.00 sec)
     
    root@localhost : plx 10:27:04> SELECT * FROM t2 GROUP BY NULL;
    +------+----+
    | a  | id |
    +------+----+
    |  10 | 1 |
    +------+----+
    1 row in set (0.00 sec)
     
    root@localhost : plx 10:30:21> SELECT MAX(a),MIN(a),MAX(id),MIN(id) FROM t2 GROUP BY NULL;
    +--------+--------+---------+---------+
    | MAX(a) | MIN(a) | MAX(id) | MIN(id) |
    +--------+--------+---------+---------+
    |   10 |   1 |    3 |    1 |
    +--------+--------+---------+---------+
    1 row in set (0.00 sec)
    
    

       是不是发现问题了?

       MAX/MIN函数取值是全局的,而不是LIMIT 1这个分组内的。

       因此,当GROUP BY NULL的时候,MAX/MIN函数是取所有数据里的最大和最小值!

       所以啊,”SELECT * FROM t HAVING id=MIN(id)”本质上是”SELECT * FROM t HAVING id=1″, 就能返回一条记录,而”SELECT * FROM t HAVING id=MAX(id)”本质上是”SELECT * FROM t HAVING id=3″,当然没有返回记录,这就是问题的根源。

       测试一下GROUP BY a,这样就对了,每个分组内只有一行,所以MAX/MIN一样大,这回是取得组内最大和最小值。

    root@localhost : plx 11:29:49> SELECT MAX(a),MIN(a),MAX(id),MIN(id) FROM t2 GROUP BY a;
    +--------+--------+---------+---------+
    | MAX(a) | MIN(a) | MAX(id) | MIN(id) |
    +--------+--------+---------+---------+
    |   1 |   1 |    3 |    3 |
    |   10 |   10 |    5 |    5 |
    +--------+--------+---------+---------+
    2 rows in set (0.00 sec)
    
    

       GROUP BY NULL时MAX/MIN的行为,是这个问题的本质,所以啊,尽量使用标准语法,玩花样SQL之前,一定要搞清楚它的行为是否与理解的一致。

    展开阅读

    相关资源

    • MySQL学习资料知识点总结

      大小:1.1 MBMySQL

      立即下载
    • MySQL核心技术与最佳实践

      MySQL核心技术与最佳实践

      大小:48 MBMySQL

      立即下载
    • MySQL8 Cookbook(中文版)

      MySQL8 Cookbook(中文版)

      MySQL 8.0的发布是MySQL发展历史上的一个重要里程碑,也是开源数据库领域内的一个大事件。针对这个版本,MySQ官方团队做了太多的工作,从查询优化到集群架构,从参数调整到特性支持,MySQL都有了革命性的变化。本书基于MySQL 8.0,以基础知识为入手点,以讲解技术特性为目标,以案例作为理论的补充,详细介绍了MySQL的方方面面,提供了超过150个高性能数据库查询与管理技巧,是MySQL入门者和管理者的必读之作。

      大小:210320 MB MySQL8

      立即下载
    • PHP&MySQL跨设备网站开发实例精粹

      PHP&MySQL跨设备网站开发实例精粹

      这本书从易学实用的角度详细讲解了PHP、HTML5语法,MySQL数据库存取,网页之间的信息传递、表单的后端处理等,提供了丰富的网站开发范例,欢迎下载

      大小:80.9 MBPHP编程

      立即下载
    • 廖雪峰 SQL教程(MySQL)

      什么是SQL?简单地说,SQL就是访问和处理关系数据库的计算机标准语言。也就是说,无论用什么编程语言(Java、Python、C++)编写程序,只要涉及到操作关系数据库,比如,一个电商网站需要把用户和商品信息存入数据库,或者一个手机游戏需要把用户的道具、通关信息存入数据库,都必须通过SQL来完成。所以,现代程序离不开关系数据库,要使用关系数据库就必须掌握SQL。在本教程中,你将学到关系数据库的基本概念,如何使用SQL操作数据库,以及一种

      大小:2.45 MBMySQL教程

      立即下载
    • MySQL开发与实践

      MySQL开发与实践

      本书作为MySQL课程的教材 系统全面地介绍了有关MySQL数据库应用开发所涉及的各类知识。全书共分16章 内容包括数据库基础、MySQL概述、MySQL语言基础、数据库和表的操作、数据库的查询、索引

      大小:45.3 MBMySQL

      立即下载

    学习笔记

    7小时20分钟前回答

    mysql中提高Order by语句查询效率的两个思路分析

    因为可能需要对数据库的记录进行重新排序。在这篇文章中,笔者就谈谈提高Order By语句查询效率的两个思路,以供大家参考。 在MySQL数据库中,Order by语句的使用频率是比较高的。但是众所周知,在使用这个语句时,往往会降低数据查询的性能。因为可能需要对数据库的记录进行重新排序。在这篇文章中,笔者就谈谈提高Order By语句查询效率的两个思路,以供大家参考。 一、建议使用一个索引来满足Order By子句。 在条件允许的情况下,笔者建议最好使用一个索引来满足Order By子句。如此的话,就可以避免额外的排序工作。这里笔者需要强调的一点是及时Order By子句不确切匹配索引,但是只要Where子句中所……

    11小时51分钟前回答

    mysql alter语句用法实例

    //主键 ALTER TABLE tablename add new_field_id int(5) UNSIGNED DEFAULT 0 NOT NULL anto_increment,ADD PRIMARY KEY (new_field_id); //增加一个新列 mysqlALTER TABLE tablename ADD fieldname fieldtype 如: ALTER TABLE t2 ADD d TIMESTAMP; ALTER TABLE infos ADD ex TINYINT NOT NULL DEFAULT '0'; //删除列 mysqlALTER TABLE table_name DROP field_name 如: ALTER TABLE t2 DROP COLUMN c; //修改原字段名称及类型 mysqlALTER TABLE tablename CHANGE old_field_name new_field_name field_type; 如: //重命名列 ALTER TABLE t1 CHANGE a b INTEGER; //改变列的类型 ALTER TABLE t1 CHANGE b b BIGINT NOT NULL; ALTER TABLE infos CHANGE list list TINYINT NOT NULL DEFAULT '0'; //重命名表 ALTER TABLE t1 RENAME t2; //加索引 mysqlALTER TABLE tablename CHANGE depno depno int(5) NOT NULL; m……