牛客网61道SQL题实战总结

1、前言

结构化查询语言(Structured Query Language)简称SQL,是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统;同时也是数据库脚本文件的扩展名。

差不多花了一周的时间做完了牛客网平台的61道SQL题,先说一说这个平台的坑:

  1. 题目含糊不清,有一些题没有准确表达意思,会让人产生误解。
  2. OJ的答案判断比较死板,不是所有正确的解法都能通过。
  3. 难度不是缓慢递增,中间有的题会非常搞人。
  4. 没有提供单独的测试数据,需要去有的题目下面找。
  5. 只支持sqlite,不支持mysql,oracle等其他SQL语言。

再讲一讲自己的刷题体会:

  1. 比较坑也是一件好事,可以训练思维的全面性,努力去寻找问题的不同切入点。
  2. 不要做完了就直接下一题!我个人最喜欢看评论,因为可以学习到前辈们的思路和解法。 首先,我会在脑海里形成自己的思路,然后和他们的思路进行对比。如果是一致的,哇,我就很开心。 如果不一致,则仔细进行比对,找到我的缺陷。
  3. SQL语句不是正确通过就万事大吉了,尽可能做多一题多解。分析每种解法的优化性能,找到 对应的使用场景。
  4. 写法要规范,注意缩进,这样每个子语句看起来就比较清晰。
  5. 在动手之前先思考一下,不要上来就急着写。
  6. 了解一些函数,比如窗口函数等,这些是利器。

如果要二刷,注意以下几点:

  1. 思考题目的真实使用场景,不要单纯做题。
  2. 遇到比较坑的题目,直接跳过,不要多花时间。
  3. 多归纳总结,必要时做一下实验。
  4. 思考一些高阶用法,降维打击。

二刷先放一下,先去刷一下LeetCode的SQL题。那里的题库更加正规,还有一些企业真题。

这么好吗?毕竟是付费的呀 - -。

2、牛客网OJ平台地址

https://www.nowcoder.com/ta/sql

3、详细答题记录(个人整理)

https://github.com/HannibalXZX/LearnSQL/tree/master/SQL%E5%AE%9E%E6%88%98-%E7%89%9B%E5%AE%A2%E7%BD%91

4、 笔记

01. left join中on和where的区别

  1. on条件是在生成临时表时使用的条件,不管on中的条件是否为真,都会返回左边表中的记录。
  2. where条件是在临时表生成好后,再对临时表进行过滤的条件。这时已经没有left join的含义(必须返回左边表的记录)了,条件不为真的就全部过滤掉。

02. 三个连接的简单区别

  • INNER JOIN 两边表同时有对应的数据,即任何一边缺失数据就不显示。
  • LEFT JOIN 会读取左边数据表的全部数据,即便右边表无对应数据。
  • RIGHT JOIN 会读取右边数据表的全部数据,即便左边表无对应数据

03. 内连和并列的区别

并列,也是等值连接。在这个过程中,实际上是没有创建出临时的新表,只是为了方便理解,可以认为两张表合并成一张新表,然后再从该表 SELECT所需的字段和记录。

内连可以不等。推荐用内连,因为,可以将连接条件标记得比较清楚。

04. SQL执行顺序(重要)

FROMWHEREGROUP BYHAVINGSELECTDISTINCTUNIONORDER BY

05. GROUP BY 和 DISTINCT

  • 当对系统的性能高并数据量大时使用 GROUP BY
  • 当对系统的性能不高时使用数据量少时两者皆可
  • 尽量使用 GROUP BY

针对网上实验结果,还有一种结论:

去重场景下,未加索引时,更偏向于使用distinct,而加索引时,distinct和group by两者都可以使用

实验过程原文链接

06. LEFT JOIN 和 IN

MySQL官方文档有说明, IN关键字适合确定数量的情况,一般效率较低,不推荐使用。能用 IN关键字的语句都可以转化为使用 JOIN的语句,推荐使用 JOIN关键字。

07. WHERE 和 HAVING

WHEREHAVING的不同之处在于, WHERE是查找之前的限定,而 HAVING是查找之后。如果使用 HAVING,必须提前筛选字段,但 WHERE不需要。 WHERE后面不能加聚合函数, HAVING后可以加聚合函数。

08. JOIN关联表中ON,WHERE后面跟条件的区别

不管 ON上的条件是否为真都会返回 LEFTRIGHT表中的记录,full则具有 LEFTRIGHT的特性的并集。 而 INNER JOIN没这个特殊性,则条件放在 ON中和 WHERE中,返回的结果集是相同的。
参考原文链接

09. EXPLAIN 函数作用

  1. 表的读取顺序
  2. 数据读取操作的操作类型
  3. 哪些索引可以使用
  4. 哪些索引被实际使用
  5. 表之间的引用
  6. 每张表有多少行被优化器查询

10. MySQL创建索引方法:ALTER TABLE和CREATE INDEX的区别

众所周知,MySQL创建索引有两种语法,即:
ALTER TABLEHeadOfStateADD INDEX(LastName,FirstName);
CREATE INDEX index_nameHeadOfState(LastName,FirstName);
那么,这两种语法有什么区别呢?

  1. CREATE INDEX必须提供索引名,对于 ALTER TABLE,如果你不提供索引名,将会自动创建;
  2. CREATE INDEX一个语句一次只能建立一个索引, ALTER TABLE可以在一个语句建立多个,如: ALTER TABLEHeadOfStateADD PRIMARY KEY(ID),ADD INDEX(LastName,FirstName);
  3. 只有 ALTER TABLE才能创建主键,

11. 强制索引

MYSQL中强制索引查询使用: SELECT*FROM table FORCE INDEX(indexname); SQLite中强制索引查询使用: SELECT*FROM table INDEXED BY indexname;

12. 严格模式

mysql的 datetime类型无法插入'0000-00-00 00:00:00',这是因为mysql开启了严格模式。

SELECT@@sql_mode 得到如下结果:

ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION

可以看到结果里面有 NO_ZERO_IN_DATE,NO_ZERO_IN_DATE。把这两个去掉,再重新设置即可。

SET GLOBAL sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';

玄学:在Navicat Premium上不行,但在mysql终端上可行

13. MYSQL子查询的坑

MySQL的 UPDATEDELETE中子查询不能为同一张表,可将查询结果再次 SELECT。在MySQL中还有一个坑,需要给子查询添加别名, 不然会抛出错误:ERROR 1248 (42000): Every derived table must have its own alias

14. 字符长度函数

char_length(): 统计的是字符长度,而 LENGTH()函数统计的是字符串的字节长度,所以 LENGTH('中')在utf8下的结果是3,而 char_length('中')的结果仍然是1。

15. EXISTS的用法

EXISTS对外表用loop逐条查询,每次查询都会查看 EXISTS的条件语句,当 EXISTS里的条件语句能够返回记录行时(无论记录行是的多少),只要能返回,条件就为真。并返回当前loop到的这条记录;

反之如果 EXISTS里的条件语句不能返回记录行,则当前loop到的这条记录被丢弃, EXISTS的条件就像一个bool条件,当能返回结果集则为true,不能返回结果集则为 false。

简而言之,使用 EXISTS需要建立内外关联。

  • 没有建立内外关联,等价于: SELECT b.emp_no FROM employees b
  1. SELECT b.emp_no FROM employees b
  2. WHERE EXISTS (SELECT emp_no FROM dept_emp)
  • 建立内外关联
  1. SELECT b.emp_no FROM employees b
  2. WHERE EXISTS (SELECT emp_no FROM dept_emp WHERE b.emp_no=emp_no)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,718评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,683评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,207评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,755评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,862评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,050评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,136评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,882评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,330评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,651评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,789评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,477评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,135评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,864评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,099评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,598评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,697评论 2 351