SQL汇总

1.SQL执行顺序

(8)SELECT (9)DISTINCT  (11)<Top Num> <select list>
(1)FROM [left_table]
(3)<join_type> JOIN <right_table>
(2)        ON <join_condition>
(4)WHERE <where_condition>
(5)GROUP BY <group_by_list>
(6)WITH <CUBE | RollUP>
(7)HAVING <having_condition>
(10)ORDER BY <order_by_list> 
SELECT 列名称 FROM 表名称 WHERE 列 运算符 值
select * from table
where  A #单个条件
where  A and B #和
where  A or B  #或
where  (A and B) or (C and D)  #优先级
where  in (" "," “," ”)  #指定针对某个列的多个可能值
where  A> 、>=、< 、<=、!=10000  #单个数值
where A between 10000 and 20000 #在某个范围内
where A like ‘%B%’  #模糊查询/搜索某种模式
where A not in、not like、not null  #否定
sign--符号,power--幂
select * from table
group by A  #将数据按组/维度划分
select * from table
group by A ,B #将数据按多维形式聚合
select A,count(*) as 客户数量 
from table
group by A  #统计数量

除了count,还有max,min,sum,avg等函数,也叫做聚合函数

select A,count(distinct Id) from table
group by A #按A分组(不重复)
select if(A like ‘%B%’,1,0) from table  #逻辑判断

4.想统计各个城市中有多少数据分析职位,其中,电商领域的职位有多少,在其中的占比

select city,
count(distinct Id),
count(distinct(if(industryField like ‘%电子商务%’,Id,null)))
from table
group by city  #占比,count函数对0,1都计数,因此用null

5.想找出各个城市,数据分析师岗位数量在500以上的城市有哪些

第一种,是使用having语句,它对聚合后的数据结果进行过滤。

WHERE 子句对被选择的列施加条件,而 HAVING 子句则对 GROUP BY 子句所产生的组施加条件。

在 SELECT 查询中,HAVING 子句必须紧随 GROUP BY 子句,并出现在 ORDER BY 子句(如果有的话)之前。

select city,count(distinct Id) from table
group by city 
having count(distinct Id) >= 500

上面的代码用了一个子查询,主要是因为在SQL Server中GROUP BY分组后,在SELECT后面显示的列里面只能显示分组的列,比如我们这里对城市分组了,那么子查询里面就只能显示城市列,显示不了其他列

第二种,是利用嵌套子查询。
子查询不能使用 ORDER BY,不过主查询可以。在子查询中,GROUP BY 可以起到同 ORDER BY 相同的作用。
返回多行数据的子查询只能同多值操作符一起使用,比如 IN 操作符。
通常情况下子查询都与 SELECT 语句一起使用;但还可以用在 INSERT 语句中。INSERT 语句可以将子查询返回的数据插入到其他表中。子查询中选取的数据可以被任何字符、日期或者数值函数所修饰;也可以用在 UPDATE 语句中。当子查询同 UPDATE 一起使用的时候,既可以更新单个列,也可更新多个列;还可以同 DELETE 语句一起使用。

select * from (
    select city,count(distinct Id) as counts from table
    group by city ) as table1
where counts >= 500
select * from table
group by A  
order by B  #将数据升序
select * from table
group by A  
order by B desc  #将数据降序

多列排序,按 "省份" 升序排列,并按 "姓名" 列降序排列

ORDER BY 省份 ASC, 姓名 DESC;
GETDATE()函数用于返回当前数据库系统的日期和时间
SELECT GETDATE()
GETUTCDATE()函数返回当前UTC(世界标准时间)日期值,即格林尼治时间(GMT) 
SELECT GETUTCDATE()
YEAR()函数以int数据类型的格式返回特定日期的年度信息
SELECT YEAR(GETDATE())
select now()  #当前的系统时间,精确到秒
select date(now())   #当前日期

week函数获得当前第几周,month函数获得当前第几个月。其余还包括,quarter,year,day,hour,minute

时间加减法

select date_add(date(now()) ,interval 1 day)

改变1为负数,达到减法的目的

求两个时间的间隔

datediff(date1,date2)或者timediff(time1,time2)
substr(字符串,从哪里开始截,截取的长度)

薪水上限的开始位置是「-」位置往后推一位。截取长度是整个字符串减去「-」所在位置,刚好是后半段我们需要的内容,不过这个内容是包含「K」的,所以最后结果还得再减去1。

select left(salary,locate("k",salary)-1) as bottomsalary,
       substr(salary,locate("-",salary)+1,length(salary)-locate("-",salary)-1) as topsalary,
       salary from table
where salary not like "%以上%"

然后计算不同城市不同工作年限的平均薪资。

select city,workyear,avg((bottomsalary+topsalary)/2) as avgsalary from(
      select left(salary,locate("k",salary)-1) as bottomsalary,
            substr(salary,locate("-",salary)+1,length(salary)-locate("-",salary)-1) as topsalary,
            city,Id,workyear from table
       where salary not like "%以上%") as table1
group by city,workyear
order by city,avgsalary

inner join等价于join
left join返回A表所有的行,B表中所有数据对应横向放在A表后面,若A表中数据行较多,那么对于B表中的字段若在A表中不存在对应数据行,则用 NULL来填充。
full join只要A表和B表中有一个关键字存在匹配,则返回两个表的所有行,没有匹配的地方自动用NULL填充。
A Full Join B = A Left Join B + A Right Join B – A Inner Join B

select a.customer_id,a.rental_date,a.return_date,b.first_name,b.last_name 
from rental a inner join customer b
on  a.customer_id=b.customer_id;
select a.customer_id,a.rental_date,a.return_date,b.first_name,b.last_name 
from rental a,customer b
where  a.customer_id=b.customer_id;

11.仅在指定的列中插入数据

INSERT INTO Customers (姓名, 城市, 省份)
VALUES ('武松', '邢台', '河北省');

15.UNION运算符用于组合两个或更多SELECT语句的结果集

UNION使用前提:UNION中的每个SELECT语句必须具有相同的列数
这些列也必须具有相似的数据类型,每个SELECT语句中的列也必须以相同的顺序排列

SELECT column_name(s) FROM table1
UNION
SELECT column_name(s) FROM table2;

UNION 运算符选择一个不同的值,即不允许重复值

SELECT column_name(s) FROM table1
UNION ALL
SELECT column_name(s) FROM table2;

允许重复值

16.ALTER TABLE 语句用于在已有的表中添加、修改或删除列

若要向表中添加列,请使用以下语法:
ALTER TABLE table_name
ADD column_name datatype
若要删除表中的列,请使用以下语法:
ALTER TABLE table_name
DROP COLUMN column_name
若要更改表中列的数据类型,请使用以下语法:
ALTER TABLE table_name
CHANGE COLUMN column_name datatype

17.约束

约束是作用于数据表中列上的规则,用于限制表中数据的类型。约束的存在保证了数据库中数据的精确性和可靠性。

约束有列级和表级之分,列级约束作用于单一的列,而表级约束作用于整张数据表。

NOT NULL 约束:保证列中数据不能有 NULL 值
DEFAULT 约束:提供该列数据未指定时所采用的默认值
UNIQUE 约束:保证列中的所有数据各不相同
主键约束:唯一标识数据表中的行/记录
外键约束:唯一标识其他表中的一条行/记录
CHECK 约束:此约束保证列中的所有值满足某一条件
索引:用于在数据库中快速创建或检索数据

约束可以在创建表时规定(通过 CREATE TABLE 语句),或者在表创建之后规定(通过 ALTER TABLE 语句)。

CREATE TABLE table_name 
column_name1 data_type(size) constraint_name, 
column_name2 data_type(size) constraint_name, 
column_name3 data_type(size) constraint_name, 
ALTER TABLE EMPLOYEES DROP CONSTRAINT EMPLOYEES_PK;

18.索引

索引是一种特殊的查询表,可以被数据库搜索引擎用来加速数据的检索。简单说来,索引就是指向表中数据的指针。数据库的索引同书籍后面的索引非常相像。

索引能够提高 SELECT 查询和 WHERE 子句的速度,但是却降低了包含 UPDATE 语句或 INSERT 语句的数据输入过程的速度。索引的创建与删除不会对表中的数据产生影响。

CREATE INDEX index_name ON table_name;
单列索引基于单一的字段创建

CREATE INDEX index_name ON 
table_name (column_name);
唯一索引不止用于提升查询性能,还用于保证数据完整性。唯一索引不允许向表中插入任何重复值

CREATE UNIQUE INDEX index_name ON
table_name (column_name);
聚簇索引在表中两个或更多的列的基础上建立

CREATE INDEX index_name ON 
table_name (column1, column2);

创建单列索引还是聚簇索引,要看每次查询中,哪些列在作为过滤条件的 WHERE 子句中最常出现。

如果只需要一列,那么就应当创建单列索引。如果作为过滤条件的 WHERE 子句用到了两个或者更多的列,那么聚簇索引就是最好的选择。

19.事务

事务是在数据库上按照一定的逻辑顺序执行的任务序列,既可以由用户手动执行,也可以由某种数据库程序自动执行。

事务实际上就是对数据库的一个或者多个更改。当你在某张表上创建更新或者删除记录的时,你就已经在使用事务了。控制事务以保证数据完整性,并对数据库错误做出处理,对数据库来说非常重要。

事务的属性
事务具有以下四个标准属性,通常用缩略词 ACID 来表示:
原子性:保证任务中的所有操作都执行完毕;否则,事务会在出现错误时终止,并回滚之前所有操作到原始状态。
一致性:如果事务成功执行,则数据库的状态得到了进行了正确的转变。
隔离性:保证不同的事务相互独立、透明地执行。
持久性:即使出现系统故障,之前成功执行的事务的结果也会持久存在。

有四个命令用于控制事务:
COMMIT:提交更改;
ROLLBACK:回滚更改;
SAVE:在事务内部创建一系列可以 ROLLBACK 的还原点;
SET TRANSACTION:命名事务;

20.锁机制

  • 共享锁:由读表操作加上的锁,加锁后其他用户只能获取该表或行的共享锁,不能获取排它锁,也就是说只能读不能写。
  • 排它锁:由写表操作加上的锁,加锁后其他用户不能获取该表或行的任何锁,典型是mysql事务中的
    锁的范围:
    行锁: 对某行记录加上锁
    表锁: 对整个表加上锁
    这样组合起来就有,行级共享锁,表级共享锁,行级排他锁,表级排他锁。
  • 加锁与解锁
    LOCK TABLES tablename WRITE;
    LOCK TABLES tablename READ;
    Insert INTO assignment VALUES (1,7513,'0000-00-00',5),(1,7513,'2003-01-20',8.5);
    UNLOCK TABLES;

  • 不同锁的优缺点及选择
    行级锁的优点及选择:
    1)在很多线程请求不同记录时减少冲突锁。
    2)事务回滚时减少改变数据。
    3)使长时间对单独的一行记录加锁成为可能。

  • 行级锁的缺点:
    1)比页级锁和表级锁消耗更多的内存。
    2)当在大量表中使用时,比页级锁和表级锁更慢,因为他需要请求更多的所资源。
    3)当需要频繁对大部分数据做 GROUP BY 操作或者需要频繁扫描整个表时,就明显的比其它锁更糟糕。
    4)使用更高层的锁的话,就能更方便的支持各种不同的类型应用程序,因为这种锁的开销比行级锁小多了。
    5)可以用应用程序级锁来代替行级锁,例如MySQL中的 GET_LOCK() 和 RELEASE_LOCK()。但它们是劝告锁(原文:These are advisory locks),因此只能用于安全可信的应用程序中。
    6)对于 InnoDB 和 BDB 表,MySQL只有在指定用 LOCK TABLES 锁表时才使用表级锁。在这两种表中,建议最好不要使用 LOCK TABLES,因为 InnoDB 自动采用行级锁,BDB 用页级锁来保证事务的隔离。

    表锁的优点及选择:
    1)很多操作都是读表。
    2)在严格条件的索引上读取和更新,当更新或者删除可以用单独的索引来读取得到时:UPDATE tbl_name SET column=value WHERE unique_key_col=key_value;DELETE FROM tbl_name WHERE unique_key_col=key_value;
    3)SELECT 和 INSERT 语句并发的执行,但是只有很少的 UPDATE 和 DELETE 语句。
    4)很多的扫描表和对全表的 GROUP BY 操作,但是没有任何写表。

    表锁的缺点:
    1)一个客户端提交了一个需要长时间运行的 SELECT 操作。
    2)其他客户端对同一个表提交了 UPDATE 操作,这个客户端就要等到 SELECT 完成了才能开始执行。
    3)其他客户端也对同一个表提交了 SELECT 请求。由于 UPDATE的优先级高于 SELECT,所以 SELECT 就会先等到 UPDATE 完成了之后才开始执行,它也在等待第一个 SELECT操作。

    21.常用字符处理函数

    ASCII(字符串)
    返回字符串表达式中最左侧的ASCII代码值

    SELECT ASCII('S'),ASCII('SQL')
    REPLACE与TRANSLATE的区别
    https://blog.csdn.net/u013361361/article/details/21126279

    UPPER(需要转换为大写的字符串)
    把传递给它的字符串转换为大写

    SELECT UPPER('sql学习之路')
    

    主要有基于规则的优化(rules)、基于成本的优化(cost)
    1)基于规则的优化
    通常是基于表查询的优化,方法有:选择最有效率的表顺序,避免select *的出现,用TRUNCATE替代DELETE等
    2)基于成本的优化
    建立索引;
    建立分区表;
    视图、函数的适当使用;
    返回更少数据(不必要的字段);
    数据库的表越少越好,表的字段越少越好;
    适当的冗余,增加计算列,提高数据库的运行效率;
    存储过程,如果采用存储过程你可以将整个业务逻辑封装在存储过程里,然后在客户端直接调用存储过程处理,这样可以减少数据库交互的成本;

    23.事务型数据库与分析型数据库的特征及二者区别?

    事务型数据库主要是实时的,面向应用的数据库,响应及时性要求很高,只关注最近一段时间的数据。就是平时搭建的服务都叫事务型数据库。
    分析型数据库主要是用于在大量数据中分析规律的,一般存储的数据时间跨度长,数据量大,对实时性要求不高,通过查询分析规律趋势,用于产品决策等,如数据仓库。

    24.谓词EXISTS

    EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False
    EXISTS 指定一个子查询,检测 行 的存在。

    语法: EXISTS subquery
    参数: subquery 是一个受限的 SELECT 语句 (不允许有 COMPUTE 子句和 INTO 关键字)。
    结果类型: Boolean 如果子查询包含行,则返回 TRUE ,否则返回 FLASE 。
    

    与集合成员资格运算符IN的区别
    IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况。
    ①exists:存在,后面一般都是子查询,当子查询返回行数时,exists返回true。
    select * from class where exists (select'x"form stu where stu.cid=class.cid)
    当in和exists在查询效率上比较时,in查询的效率快于exists的查询效率
    exists(xxxxx)后面的子查询被称做相关子查询, 他是不返回列表的值的.
    只是返回一个ture或false的结果

    其运行方式是先运行主查询一次 再去子查询里查询与其对应的结果 如果存在,返回ture则输出,反之返回false则不输出,再根据主查询中的每一行去子查询里去查询.

    执行顺序如下:
    首先执行一次外部查询
    对于外部查询中的每一行分别执行一次子查询,而且每次执行子查询时都会引用外部查询中当前行的值。
    使用子查询的结果来确定外部查询的结果集。

    ②in:包含
    查询和所有女生年龄相同的男生
    select * from stu where sex='男' and age in(select age from stu where sex='女')
    in()后面的子查询 是返回结果集的,换句话说执行次序和exists()不一样.子查询先产生结果集,
    然后主查询再去结果集里去找符合要求的字段列表去.符合要求的输出,反之则不输出.

    查询所有选修了1号课程的学生姓名

    思路分析:
       本查询涉及Student和SC关系
       在Student中依次取每个元组的Sno值,用此值去检查SC关系
       若SC中存在这样的元组,其Sno值等于此Student.Sno值,并且其Cno= '1',则取此Student.Sname送入结果关系
       用嵌套查询
         SELECT Sname
         FROM Student
         WHERE EXISTS
                       (SELECT *
                        FROM SC
                        WHERE Sno=Student.Sno AND Cno= ' 1 '); 
       用连接运算
        SELECT Sname
        FROM Student, SC
        WHERE Student.Sno=SC.Sno AND SC.Cno= '1';
    

    25.谓词any、all

    这两个都是用于子查询的
    any 是任意一个
    all 是所有

    any表示有任何一个满足就返回true,all表示全部都满足才返回true

    select * from student where 班级=’01’ and age > all (select age from student where 班级=’02’); 
    就是说,查询出01班中,年龄大于 02班所有人的同学 
    select * from student where 班级=’01’ and age > (select max(age) from student where 班级=’02’);
    select * from student where 班级=’01’ and age > any (select age from student where 班级=’02’); 
    就是说,查询出01班中,年龄大于 02班任意一个 的 同学 
    select * from student where 班级=’01’ and age > (select min(age) from student where 班级=’02’);
    

    查询其他系中比计算机科学某一学生年龄小的学生姓名和年龄

    SELECT Sname,Sage
    FROM    Student
    WHERE Sage < ANY (SELECT  Sage
                                         FROM    Student
                                         WHERE Sdept= ' CS ')
               AND Sdept <> ‘CS ' ;     
    SELECT Sname,Sage
    FROM   Student
    WHERE Sage < (SELECT MAX(Sage)
                                FROM Student
                                WHERE Sdept= ‘CS ')
               AND Sdept <> ' CS ’ ;
    

    查询其他系中比计算机科学系所有学生年龄都小的学生姓名及年龄

    用ALL谓词
        SELECT Sname,Sage
        FROM Student
        WHERE Sage < ALL
                               (SELECT Sage
                                FROM Student
                                WHERE Sdept= ' CS ')
               AND Sdept <> ' CS ’;
    用聚集函数
            SELECT Sname,Sage
            FROM Student
            WHERE Sage < 
                                   (SELECT MIN(Sage)
                                    FROM Student
                                    WHERE Sdept= ' CS ')
                  AND Sdept <>' CS ’;
    

    26.视图

    视图正如其名字的含义一样,是另一种查看数据的入口。
    常规视图本身并不存储实际的数据,而仅仅是由SELECT语句组成的查询定义的虚拟表 。
    视图是一个虚拟的表,是一个表中的数据经过某种筛选后的显示方式,视图由一个预定义的查询select语句组成。
    视图最多可以有 1024 列

    视图的特点
    视图中的数据并不属于视图本身,而是属于基本的表,对视图可以像表一样进行insert,update,delete操作。
    视图不能被修改,表修改或者删除后应该删除视图再重建。
    视图的数量没有限制,但是命名不能和视图以及表重复,具有唯一性。
    视图可以被嵌套,一个视图中可以嵌套另一个视图。
    视图不能索引,不能有相关联的触发器和默认值,sql server不能在视图后使用order by排序

    视图的功能
    1.简化用户操作
    2.能以不同的角度观察同一个数据库
    3.对重构数据库提供了逻辑独立性:
    利用视图将需要的数据合并或者筛选,但是不影响原表的数据和结构
    3.对机密数据提供安全保护:
    可以建立不同的视图对用不同的用户,以达到安全的目的。

    CREATE VIEW view_name AS
    SELECT column1, column2.....
    FROM table_name
    WHERE [condition];
    
    CREATE VIEW actor_name_view(first_name_v,last_name_v) AS
    SELECT first_name,last_name
    FROM actor
    

    27.触发器

    何为触发器?在SQL Server里面也就是对某一个表的一定的操作,触发某种条件,从而执行的一段程序。触发器是一个特殊的存储过程。
    常见的触发器有三种:分别应用于Insert , Update , Delete 事件。

    CREATE TRIGGER trigger_name
     ON table_name
     [WITH ENCRYPTION]
      FOR | AFTER | INSTEAD OF [DELETE, INSERT, UPDATE]
      T-SQL语句
    --with encryption 表示加密触发器定义的sql文本
    --delete,insert,update指定触发器的类型</pre>
         Create Trigger truStudent 
           On Student                         --在Student表中创建触发器 
           for Update                          --为什么事件触发 
         As                                        --事件触发后所要做的事情 
           if Update(StudentID)            
           begin 
             Update BorrowRecord 
               Set StudentID=i.StudentID 
               From BorrowRecord br , Deleted   d ,Inserted i      --Deleted和Inserted临时表 
               Where br.StudentID=d.StudentID 
    

    一个Update 的过程可以看作为:生成新的记录到Inserted表,复制旧的记录到Deleted表,然后删除Student记录并写入新纪录。

    2)如果该学生已经毕业,我希望删除他的学号的同时,也删除它的借书记录。

       对于2,创建一个Delete触发器 
         Create trigger trdStudent 
           On Student 
           for Delete 
           Delete BorrowRecord 
             From BorrowRecord br , Delted d 
             Where br.StudentID=d.StudentID 
    

    28.SQL优化问题

    https://mp.weixin.qq.com/s/6gqDy8VsMWUSgvc8zhnB6Q

    29.ifnull函数与coalesce()函数

    1)ifnull
    ifnull函数用于在表达式是NULL时,从另外一个表达式获得值,它可以用于大多数数据类型,但值与替代值必须是同一数据类型

    IFNULL(expr1,expr2)
    如果 expr1 不是 NULL,IFNULL() 返回 expr1,否则它返回 expr2。
    

    2)coalesce函数用指定值代替NULL,其不同点在于,它可以接受一个数据集,一次检查其中的每一个值,知道发现一个非null值,如果没有找到非null值,它会返回一个值
    将空值替换成其他值
    返回第一个非空值

    ②表达式:
    COALESCE是一个函数, (expression_1, expression_2, ...,expression_n)依次参考各参数表达式,遇到非null值即停止并返回该值。如果所有的表达式都是空值,最终将返回一个空值。使用COALESCE在于大部分包含空值的表达式最终将返回空值。

    30.instr函数

    INSTR(C1,C2,I,J) 在一个字符串中搜索指定的字符,返回发现指定的字符的位置;
    C1 被搜索的字符串
    C2 希望搜索的字符串
    I 搜索的开始位置,默认为1
    J 出现的位置,默认为1
    SQL> select instr("abcde",'b');

    结果是2,即在字符串“abcde”里面,字符串“b”出现在第2个位置。如果没有找到,则返回0

    31.decode函数

    decode(条件,值1,翻译值1,值2,翻译值2,...值n,翻译值n,缺省值)

      该函数的含义如下:
      IF 条件=值1 THEN
      RETURN(翻译值1)
      ELSIF 条件=值2 THEN
      RETURN(翻译值2)
      ......
      ELSIF 条件=值n THEN