龙空技术网

SQL自学总结

下小雨2018 3650

前言:

当前姐妹们对“sql将一行拆成多行”大致比较关切,大家都想要学习一些“sql将一行拆成多行”的相关文章。那么小编在网上收集了一些有关“sql将一行拆成多行””的相关内容,希望小伙伴们能喜欢,我们一起来了解一下吧!

因为工作原因,要和数据库打交道,除了公司内网自带的指标平台、可供下载固定格式固定内容的有限张表之外,更多情况下需要自己从数据库中灵活的取数,因此必须迅速学习和使用SQL语言。事实上,作为使用最为广泛的数据库语言,SQL是有些明显的优点的:通用性强,几乎所有重要的DSMS都支持SQL,针对不同的数据库,如hivesql、mysql、sql server、oracle等,sql语法总体上大同小异,只是细微处的差别;简单易学,关键词很少,且贴近英文语法,普通的使用,一到两周应该可以初步使用。我们公司使用的是ADHOC(advanced data handler for on-line control)平台下的,hiveSQL语法,我的学习也是先基于标准SQL语法学习的。为了鼓励大家,我想说我也是纯小白一枚,零基础,现在谈谈我的学习顺序和一点心得。

首先声明,我们公司使用的数据库,使用的代码结构并不复杂,不需要很高级的语句,只用最基本的select、join、group by就可以,只要你语法正确、能顺利跑下来,就可以了。所以,一开始我就奔着实用的态度选取资料学习的;大而全的专业书籍直接pass、高级技巧先放在一边,号召“打好基础”、一来就推荐好几本类似《数据库基础》的纯理论基础大部头也只能弃之不用。经过仔细搜索,我确定的方法是:纸质书一本《SQL必知必会(第4版)》(Ben Forta),在线刷题网站一个SQLZOO,。书看两遍,题刷两遍,就能实现掌握基础知识,大约70%?吧。学完这些,就可以硬着头皮开始尝试取数了,当然刚开始会有很多报错,但是通过错误能学到更多、进步更快。这时要想进阶的话,书可以看更全更专业一些的,刷题的话,可能要找找英文网站或者用一个数据库管理软件自己创建数据库然后练习。关于自学方法和资料网上一搜一大堆,可以自己关注下吧,这里不多说哦。

宁可少活二十年 立志拿下SQL!

我想分享的是我学习的一点总结,和初始阶段经过的一些雷区。

首先说语句结构。SQL 语句有一个让大部分人都感到困惑的特性,就是SQL 语句的执行顺序跟其语句的语法顺序并不一致。当然也温馨提示下,并非所有的数据库对 SQL 语句使用相同的解析方式,这时具体情况具体对待吧,如果出现报错,可以查阅相关帮助文档或咨询度娘。

SQL执行顺序

如图所示,我们书写的时候,要注意关键字的顺序,比如select,from写完后,要先where,然后group by,然后having,order by永远是放在最后面。但是实际执行的时候,系统先跳过select,从from开始、加载需要处理的表格,然后where进行初步过滤,注意这个过滤是在分组前进行过滤,然后通过group by进行分组,再利用having进行分组后的过滤、筛选满足条件的组,然后才是select及其之后的语句。理解了这一点,也就很容易理解一些语法规定了,例如:where条件中不能跟聚合函数,而having后面可以;执行顺序where>聚合函数(sum,min,max,avg,count)>having,order by是最后的显示结果进行排序,必须放于最后,等等规定。

其次,是一些关键而重要的关键词的使用。

(1)LIKE关键字,Like中最好只用%通配符。例如,要显示包含单词“United”为名称的国家:WHERE name LIKE '%United%';(正确),WHERE name LIKE '*United*'(报错)。很多朋友会问,为什么我在以上查询时用“%”而不用“*”?我也查了资料,表明:%表示包含零个或更多字符的任意字符串。在搜索串中,%表示任何字符出现任意次数。百分号很兼容,但是其他的通配符都不一定兼容。也有说,星号往往使用在首尾的时候,例如姓张的名字:’张*’,或以强结尾:’*强’,等等。但为了保险起见,我建议以后在使用like关键字时,优先用%通配符。另外,注意“或”的用法,例如:提取以A或B开头的国家名称,

where name like ’A%’ or ’B%’(错误),where name like ('A%' or 'B%' )(错误),

WHERE name LIKE 'A%' OR name LIKE 'B%';(正确)。

(2)In,当结果不止一个时使用。例如:where name in (‘France’, ‘Germany’, ‘Italy’),这里,一是注意要用圆括号,二是,内容如果是字符串,要用英文状态下的单引号。这里还有些雷区,例如题目:选取在阿根廷Argentina及澳大利亞 Australia所在的洲份中,

where continent in (select continent from world where name in ('Argentina','Australia‘) ) (正确)

注意:这里,嵌套括号中的结果不止一个,就要用in(),而不能用等于=号,否则出错。类似的,>,<,>=等等,后面都只能跟一个值,如果值多于一个,要用all,例如:where 25000000>= all(select population from world b where b.continent = a.continent ),如果省了all,则会报错。

另外有一个雷区,in的对立面并不是NOT IN!not in等价的含义是<> all,例如In(‘A’,’B’):A或者B;not in (‘A’,’B’):不是A且B。为避免混淆,最好尽量避免或使用not in。

(3)关于聚集函数。为方便数据统计的检索,SQL给出了5个聚集函数(aggregate function),COUNT,SUM,AVG,MAX,MIN,计算并返回一个值。SQL的聚集函数在各种主要SQL实现中得到了相当一致的支持。聚集函数使用语法简单,尤其当group by与聚合函数配合,十分好用!要求什么的聚合函数,就先按照它来group by,然后直接count即可。不过,也有一些雷区要注意:

①在不用聚合函数的时候,单独用group by,group by 子句中必须包含所有的列,否则会报错,但此时虽然成功执行了,group by在这里并没有发挥任何的作用,完全可以不用;若不用聚合函数,就是按照group by后面字段的顺序,把相同内容归纳在一起

③如果只有聚合函数,而没有group by,则聚合函数用于聚合整个结果集 (匹配WHERE子句的所有行),相当于只分一组。

④where后面不能放聚合函数!无论是count还是sum。那么如何解决呢,使用HAVING关键字!例如:having sum(amount) >100

⑤order by 后面是可以跟聚合函数的,即可以用聚合函数排序。

另外,除了Count(*)函数外,所有的聚合函数都忽略NULL值。

(4)注意语句末尾的分号!SQL是不区分大小写的,也会忽略所有的空格。所以,SQL语句可以写成多行,但是写成长长的一行也是完全没有错的。但是,每一句话结束,如果不加分号,则出错。这里注意,select,create table,insert into 语句都是完整的一句话,分号结束。例如:

create table games (yr int,city varchar(255)) ;

insert into games (yr,city) values (2004,'Athens') ;

insert into games (yr,city) values (2008,'Beijing') ;

insert into games (yr,city) values (2012,'London') ;

SELECT * FROM games;

平时若只有一句话(例如select),可能没加分号也能执行,但如果涉及创建表、插入、改写,必须注意分号。值得一提的是case when语句,case when语句分为简单case函数和case搜索函数,具体含义自行百度,但是例如:SELECT name, (逗号不可丢!case when本质上还是一个字段的选取!)CASE WHEN continent=‘Oceania’ THEN (不用加continent=) 'Australasia’ ELSE continent (不可省) END。最后的End容易丢,千万不要忘记。

(5)最后,说两个典型小问题的解决方法,看了很受启发。一是,最后排序时若要将某一类放在最前或最后,可以利用case when,巧妙的引用辅助列,帮助排序。例如:

①ORDER BY (case when subject in ('Physics','Chemistry') then 1 else 0 end ), subject, winner

结果:科目为(‘Physics’,’Chemistry’) 的排在最后,其余科目按subject升序排列,

②ORDER BY (case when subject in ('Physics','Chemistry') then 1 else 0 end ) desc, yr desc, winner

结果:将(‘Physics’,’Chemistry’) 排在最前;同一科目种类时,按年份从新到老;同一科目、同一年份时,按获奖者名字升序排列。

二是,一个经典问题:分组后取每组的前几条记录。这里看一个例子吧。

例:已知一个表, StudentGrade (stuid--学号, subid--课程号, grade--成绩)。PRIMARY KEY (stuid, subid)。

想要:查询每门课程的前2名成绩。

方法①:

select distinct * from studentgrade as t1

where stuid in

(select top 2 stuid from studentgrade as t2

where t1.subid=t2.subid

order by t2.grade desc) order by subid, grade desc

思路:相同的表格自联结,第二个表格将相同学科的所有学生按成绩排序-倒序,选取前二。注意,mysql不支持select top n的语法!但是mysql可用limit来实现相关功能。

方法②:

select * from StudentGrade a

where (select count(1) from studentGrade b

where b.subId=a.subId and b.grade >= a.grade) <=2

思路:第一个>=号,限制了查询条件是相同科目下成绩从大往小排,第二个<=号,表示筛选个数是2个(从1开始的)。

注意,这里大于等于、小于等于容易弄错,尤其是第二个。

方法③:

select * from StudentGrade a

where (select count(1) from StudentGrade b

where b.subid=a.subid and b.grade> a.grade) <=1

order by subId, grade desc

思路:这两张表思路相同:相同表格自联结,返回相同学科并且成绩大于a表的影响行数。这就是查询条件,再按 subId,grade 排序。

SQL才入手两周,学习代码一定要实践,一定要实践,一定要实践(重要的事情说三遍)!毕竟不是科班出身,学习不够系统,只能通过不断实践总结和不断踩雷排雷来进步了,但是,重复重复重复,是时候发扬匠心精神了!

如切如磋 如琢如磨 数据人也要有匠心!

标签: #sql将一行拆成多行 #oracle声明同一sql多次使用 #sql语句查询忽略大小写 #sqlserver忽略大小写