+# SQL
提示:sql


文章目录

  • 前言
  • 一、理论
    • 1.[SQL编写顺序](https://m.baidu.com/sf?pd=topone_trustpaper&resource_id=55858&word=sql%E8%AF%AD%E5%8F%A5%E6%89%A7%E8%A1%8C%E9%A1%BA%E5%BA%8F&ext=%7B%22url%22:%22https:%5C/%5C/www.xinzhiweike.com%5C/wenda%5C/1669391857690947%22,%22srcid%22:%2236402%22,%22jumptype%22:%22text%22,%22urlsign%22:%227202578123387254602%22,%22sitesign%22:%2210673256210323568163%22,%22query%22:%22sql%5Cu6267%5Cu884c%5Cu987a%5Cu5e8f%22,%22token%22:%221847f8%22%7D&top=%7B%22sfhs%22:1%7D&atn=index&lid=6442872996937449203):
    • 2.[SQL中的锁](http://t.csdn.cn/JwpCz)
    • 3.面试题
  • 二、数据的增删改
    • 1. 插入
      • 1)insert
      • 2)replace
    • 2. 更新:
      • 1)设置为新值
      • 2)根据已有值替换
    • 3.删除:delete from和drop table
      • 1)根据条件删除
      • 2)全部删除(表清空,包含自增计数器重置)
  • 三、表与索引操作
    • 1. 表的创建、修改与删除
      • 1)创建表
      • 2)修改表
      • 3)删除表
    • 2.索引创建、删除与使用:
      • 1)创建索引
      • 2)删除索引
      • 3)索引的使用
      • 4)[sql回表及索引优化SQL场景](https://www.cnblogs.com/taojietaoge/archive/2022/04/23/16167188.html)
  • 四、SQL基础:
    • 1.列重新命名
    • 2.去重
    • 3.排序
    • 4.where条件谓词
      • 1)且与并
      • 2)like匹配、regexp
      • 3)RLIKE后面可以跟正则表达式
      • 4)in
      • 5)exists
    • 5.使用聚合函数汇总数据
    • 6.分组语句的一般形式:
    • 7.多表查询
      • 1)子查询:
      • 2)链接查询:
        • 1. 内连接:
        • 2. 外连接
        • 3. 交叉连接:cross join
  • 五、常用函数
    • 1.保留小数
    • 2.条件函数:
      • 1)case
      • 2.)if、ifnull:
    • 3.日期函数
      • 1)格式转化和获取当前时间current_date
      • 2)时间截取
        • 1. 年月日、时分秒提取
        • 2. 返回名字:
        • 3. 计算天:
        • 4. 计算周:
        • 5. 季度: QUARTER(返回date一年中的季度,范围1到4)
      • 3)日期差计算
        • 1.TIMESTAMPDIFF
        • 2. datedff
        • 3. date_sub
        • 4. date_add
        • 5. PERIOD_ADD(P,N)
        • 6. PERIOD_DIFF(P1,P2)
    • 4.文本函数
      • 1)分割:substring_index
      • 2)替换:replace
      • 3)截取:substr、substring
      • 4)格式化:trim和ltrim(rtrim())
      • 5)定位:instr
      • 6)长度:length、CHAR_LENGTH
      • 7)连接
      • 8)大小写
    • 5. 窗口函数
      • 1)序号函数:
        • 1. row_number() over partition by
        • 2.dense_rank() over()
      • 2) 头尾函数: first_val/ last_val/nth_value
      • 3) lead、lag前后函数
      • 4) 分布函数:percent_rank()/cume_dist()
      • 5) 聚合函数 count() over/sum() over
    • 6.比较函数greatest,least,max,min
  • 六、限制结果集
    • 1.组合查询
      • 1)解析
      • 2)union
      • 3)union all
    • 2.limit用法:
    • 3.top
    • 4.eg
  • 七、综合练习
  • 八、效率:
    • 1.like
    • 2.limit
    • 3.with as
  • 总结

前言

提示:这里可以添加本文要记录的大概内容:

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


提示:以下是本篇文章正文内容,下面案例可供参考

一、理论

1.SQL编写顺序:

FROM、ON 、JOIN、WHERE、GROUP BY、AGG_FUNC、WITH、HAVING、SELECT、UNION、DISTINCT 、ORDER BY、LIMIT。
在实际执行过程中,每个步骤都会为下一个步骤生成一个虚拟表,这个虚拟表将作为下一个执行步骤的数据。
1、FROM:选择FROM后面跟的表,产生虚拟表1。
2、ON:ON是JOIN的连接条件,符合连接条件的行会被记录在虚拟表2中。
3、JOIN:如果指定了LEFT JOIN,那么保留表中未匹配的行就会作为外部行添加到虚拟表2中,产生虚拟表3。如果有多个JOIN链接,会重复执行步骤1~3,直到处理完所有表。
4、WHERE:对虚拟表3进行WHERE条件过滤,符合条件的记录会被插入到虚拟表4中。
5、GROUP BY:根据GROUP BY子句中的列,对虚拟表4中的记录进行分组操作,产生虚拟表5。
6、AGG_FUNC:常用的 Aggregate 函数包涵以下几种:(AVG:返回平均值)、(COUNT:返回行数)、(FIRST:返回第一个记录的值)、(LAST:返回最后一个记录的值)、(MAX: 返回最大值)、(MIN:返回最小值)、(SUM: 返回总和)。
7、WITH对虚拟表5应用ROLLUP或CUBE选项,生成虚拟表 6。
8、HAVING:对虚拟表6进行HAVING过滤,符合条件的记录会被插入到虚拟表7中。
9、SELECT:SELECT到一步才执行,选择指定的列,插入到虚拟表8中。
10、UNION:UNION连接的两个SELECT查询语句,会重复执行步骤1~9,产生两个虚拟表9,UNION会将这些记录合并到虚拟表10中。
11、DISTINCT将重复的行从虚拟表10中移除,产生虚拟表 11。DISTINCT用来删除重复行,只保留唯一的。
12、ORDER BY: 将虚拟表11中的记录进行排序,虚拟表12。
13、LIMIT:取出指定行的记录,返回结果集。

2.SQL中的锁

3.面试题

  1. 牛客数据库面试题
  2. mysql面试题

二、数据的增删改

1. 插入

1)insert

普通插入(全字段):INSERT INTO table_name VALUES (value1, value2, …)
普通插入(限定字段):INSERT INTO table_name (column1, column2, …) VALUES (value1, value2, …)
多条一次性插入:INSERT INTO table_name (column1, column2, …) VALUES (value1_1, value1_2, …), (value2_1, value2_2, …), …
从另一个表导入:INSERT INTO table_name SELECT col或* FROM table_name2 [WHERE key=value]

#字段id auto_increment,uid,exam_id,start_time, submit_time, score
#id为自动增长
insert into  exam_record(uid,exam_id,start_time, submit_time, score) values (1001,9001,"2021-09-01 10:11:12",'2021-09-01 23:01:12', 90) # id不填
insert into  exam_record values (NULL, 1001,9001,"2021-09-01 10:11:12",'2021-09-01 23:01:12', 90) #id=NULL自动增长
#关键字NULL可以用DEFAULT替代。

2)replace

replace into 跟 insert into功能类似,不同点在于:replace into 首先尝试插入数据到表中,如果发现表中已经有此行数据(根据主键或者唯一索引判断)则先删除此行数据,然后插入新的数据;否则,直接插入新数据。
要注意的是:插入数据的表必须有主键或者是唯一索引!否则的话,replace into 会直接插入数据,这将导致表中出现重复的数据。

2. 更新:

1)设置为新值

UPDATE table_name SET column_name=new_value [, column_name2=new_value2] [WHERE column_name3=value3]

2)根据已有值替换

UPDATE table_name SET key1=replace(key1, ‘查找内容’, ‘替换成内容’) [WHERE column_name3=value3]

UPDATE examination_info
SET tag = "Python"
WHERE tag = "PYTHON";
#当tag为PYTHON时,修改tag为Python
UPDATE examination_info
SET tag = REPLACE(tag, "PYTHON", "Python")
WHERE tag = "PYTHON";
#不仅可用于整体替换,还能做子串替换,例如要实现将tag中所有的PYTHON替换为Python(如CPYTHON=>CPython)
update exam_record
set submit_time='2099-01-01 00:00:00',score=0
where start_time<"2021-09-01" and score is null

3.删除:delete from和drop table

1)根据条件删除

DELETE FROM tb_name[WHERE options][ [ ORDER BY fields ] LIMIT n ]

2)全部删除(表清空,包含自增计数器重置)

TRUNCATE tb_name

三、表与索引操作

1. 表的创建、修改与删除

表的创建和修改可以通过如下代码查看表的结构进行确认

SHOW FULL FIELDS FROM user_info

1)创建表

1.1 直接创建表:

CREATE TABLE
[IF NOT EXISTS] tb_name -- 不存在才创建,存在就跳过
(column_name1 data_type1 -- 列名和类型必选[ PRIMARY KEY -- 可选的约束,主键| FOREIGN KEY -- 外键,引用其他表的键值| AUTO_INCREMENT -- 自增ID| COMMENT comment -- 列注释(评论)| DEFAULT default_value -- 默认值(可用当前时间current_timestamp)| UNIQUE -- 唯一性约束,不允许两条记录该列值相同| NOT NULL -- 该列非空], ...
) [CHARACTER SET charset] -- 字符集编码
[COLLATE collate_value] -- 列排序和比较时的规则(是否区分大小写等)

举个栗子

create table user_info_vip(
id int(11) not null  primary key auto_increment comment '自增ID',
uid int(11) not null unique  key  comment "用户ID" ,
nick_name varchar(64) comment "昵称",
achievement int(11) default 0 comment "成就值",level int(11) comment "用户等级",job varchar(32) comment "职业方向",register_time datetime default current_timestamp comment "注册时间"
)CHARACTER SET utf8 COLLATE utf8_general_ci;
# 或者 ")default charset=utf8"

1.2 从另一张表复制表结构创建表:

CREATE TABLE tb_name LIKE tb_name_old

1.3 从另一张表的查询结果创建表:

CREATE TABLE tb_name AS SELECT * FROM tb_name_old WHERE options

2)修改表

ALTER TABLE 表名 修改选项 。选项集合:

   { ADD COLUMN <列名> <类型> [after  col2] -- 在col2后增加列| CHANGE COLUMN <旧列名> <新列名> <新列类型> [default default_value] -- 修改列名或类型、默认值| ALTER COLUMN <列名> { SET DEFAULT <默认值> | DROP DEFAULT } -- 修改/删除 列的默认值| MODIFY COLUMN <列名> <类型> [default default_value   AFTER col2] -- 修改列类型、默认值、位置| DROP COLUMN <列名> -- 删除列| RENAME TO <新表名> -- 修改表名| CHARACTER SET <字符集名> -- 修改字符集| COLLATE <校对规则名> } -- 修改校对规则(比较和排序时用到)

3)删除表

DROP TABLE [IF EXISTS] 表名1 [ ,表名2]。

举个栗子

drop table if exists
exam_record_2011, exam_record_2012, exam_record_2013, exam_record_2014;
#查看表是否删除
SELECT TABLE_NAME FROM information_schema.TABLES
WHERE TABLE_NAME LIKE \'exam\_record\_201_\'

2.索引创建、删除与使用:

1)创建索引

1.1 create方式创建索引:

CREATE[UNIQUE -- 唯一索引| FULLTEXT -- 全文索引] INDEX index_name ON table_name -- 不指定唯一或全文时默认普通索引(column1[(length) [DESC|ASC]] [,column2,...]) -- 可以对多列建立组合索引

举个栗子

create  index idx_duration on examination_info(duration);
create unique index  uniq_idx_exam_id on examination_info(exam_id);
create fulltext index full_idx_tag on examination_info(tag)
#在duration列创建普通索引idx_duration
#在exam_id列创建唯一性索引uniq_idx_exam_id
#在tag列创建全文索引full_idx_tag。SHOW INDEX FROM examination_info
#查看索引

1.2 alter方式创建索引:

ALTER TABLE tb_name ADD [UNIQUE | FULLTEXT] [INDEX] index_content(content)

2)删除索引

2.1 drop方式删除索引:

DROP INDEX <索引名> ON <表名>

2.2 alter方式删除索引:

ALTER TABLE <表名> DROP INDEX <索引名>

3)索引的使用

  • 确定一个查询是否覆盖索引,只需要explain sql语句看Extra的结果是否是“Using index”即可。
  • 索引使用时满足最左前缀匹配原则,即对于组合索引(col1, col2),在不考虑引擎优化时,条件必须是col1在前col2在后,或者只使用col1,索引才会生效;
  • 索引不包含有NULL值的列
  • 一个查询只使用一次索引,where中如果使用了索引,order by就不会使用
  • like做字段比较时只有前缀确定时才会使用索引
  • 在列上进行运算后不会使用索引,如year(start_time)<2020不会使用start_time上的索引

4)sql回表及索引优化SQL场景

四、SQL基础:

1.列重新命名

示例:SQL 语句是由简单的英语单词构成的。这些单词称为关键字,每个 SQL 语句都是由一个或多个关键字构成。其中最经常使用的 SQL 语句就是 SELECT 语句了,它的用途是从一个或多个表中查询信息。
改变列标题(取别名)
语法:
1.列名 | 表达式 [ AS ] 新列名
2.列名 | 表达式 新列名
3.新列名=列名 | 表达式

2.去重

SELECT DISTINCT(device_id) FROM user_profile
SELECT DISTINCT device_id FROM user_profile

3.排序

ORDER BY <列名> [ASC | DESC ],<列名> [ASC | DESC ],…
按<列名>进行升序(ASC)或降序(DESC)排序, 当[ASC | DESC ]省略时默认升序

4.where条件谓词

1)且与并

and相当于&&,or相当于||

2)like匹配、regexp

_:匹配任意一个字符;
%:匹配0个或多个字符;
[ ]:匹配[ ]中的任意一个字符(若要比较的字符是连续的,则可以用连字符“-”表 达 );
[^ ]:不匹配[ ]中的任意一个字符。
like模糊查询会引起全表扫描,速度比较慢,应该尽量避免使用like关键字进行模糊查询。

where prod_desc like '%toy%'
where prod_desc regexp 'toy'
#等价

3)RLIKE后面可以跟正则表达式

1、字符^

意义:表示匹配的字符必须在最前边。

例如:^A不匹配“an A”中的‘A’,但匹配“An A”中最前面的‘A’。

2、字符$

意义:与^类似,匹配最末的字符。

例如:t$不匹配“eater”中的‘t’,但匹配“eat”中的‘t’。

3、字符[0-9]

意义:字符列表,匹配列出中的任一个字符。你可以通过连字符-指出字符范围。

例如:[abc]跟[a-c]一样。它们匹配“brisket”中的‘b’和“ache”中的‘c’。

4、字符+

意义:匹配+号前面的字符1次及以上。等价于{1,}。

例如:a+匹配“candy”中的‘a’和“caaaaaaandy”中的所有‘a’。
5.例题:rlike使用
来源:可参考https://www.yulucn.com/question/4866556442

4)in

select device_id,university,gpa
from user_profile
where (university,gpa) in (select university,min(gpa) from user_profile group by university)
order by university

5)exists

当存在0级用户未完成试卷数大于2时, 筛选存在性条件:WHERE EXISTS (SELECT uid FROM t_tag_count WHERE level = 0 AND incomplete_cnt > 2)

5.使用聚合函数汇总数据

常见统计函数:
COUNT(【Shift+8】):统计表中元组个数;
COUNT([DISTINCT] <列名>):统计本列列值个数;
SUM( <列名> ):计算列值总和;
AVG( <列名> ):计算列值平均值;
MAX( <列名> ):求列值最大值;
MIN( <列名> ): 求列值最小值。
1.上述函数中除COUNT(【Shift+8】)外,其他函数在计算过程中均忽略NULL值。
2.统计函数不能出现在WHERE子句中。
eg:错误的 -> SELECT 学号 FROM 成绩表 WHERE 成绩 = MAX(成绩)

6.分组语句的一般形式:

[GROUP BY ] <列名> [HAVING ]

7.多表查询

1)子查询:

用子查询过滤字段

 select <列名> from user_profile where id=(select id from user where university='浙江大学')

子查询作为计算字段使用

select cust name , cust state,
(select count(*) from orders where orders.cust id = customers.cust id)
from customers

2)链接查询:

  • 连接条件放在using: 左连接试卷作答表和试卷信息表:exam_record LEFT JOIN examination_info USING(exam_id)
  • 连接条件放在on后: FROM t_tag_count JOIN t_tag_count ON UPPER(a.tag) = b.tag and a.tag != b.tag and a.answer_cnt < 3;

1. 内连接:

(I)等值连接:

SELECT <列名> FROM table1 a,table2 b WHERE a.id = b.id;

(II)非等值连接:

 SELECT <列名> FROM table1 a,table2 b WHERE salary BETWEEN b.lowest_sal AND b.highest_sal;

(III)自连接:

SELECT <列名> FROM table a,table b
WHERE a.manager_id=b.employee_id;

(IV)内连接:inner join,连接条件放在on后(只写join默认内连接)

2. 外连接

(I)左外连接:left join,右表只列出ON后条件与左表满足的部分
(II)右外连接:right join

 Select * from   (Select *from user_profile)a -- 表别名Right join(Select *From question_practice_detail) b -- 表别名On a.device_id = b.device_id —给出链接条件

(III)全外连接:full join

3. 交叉连接:cross join

如果在匹配时没用限制匹配条件,这时就会导致笛卡尔积。表示两个表中的每一行数据任意组合,即假设表A中有n行数据,表b中有m行数据,没有限制匹 配条件的话,最终输出的结果就会有m*n行数据.结果行数会是天文数字,所以在写匹配时,一定不要忘了加上匹配条件。

五、常用函数

1.保留小数

round(<列名>,len):四舍五入,len表示保留小数点位数。

2.条件函数:

1)case

case when-then [else] end ,语法如下:
CASE 测试表达式
WHEN 简单表达式1 THEN 结果表达式1
WHEN 简单表达式2 THEN 结果表达式2 …
WHEN 简单表达式n THEN 结果表达式n
[ ELSE 结果表达式n+1 ]
END

select case when age<25||age is null then '25岁以下'else '25岁及以上' end age_cut,count(*) number
from user_profile
group by age_cut

2.)if、ifnull:

select if(age<20,'20岁以下',if(age>=25,'25岁及以上','其他')) age_cut from user_profileselect sum(if(score is null,1,0))

3.日期函数

常见的日期数据格式有两种:‘yyyy-MM-dd’ 和 ‘yyyyMMdd’。

1)格式转化和获取当前时间current_date

(I)时间戳-日期格式转化
时间戳是数据库中自动生成的唯一二进制数字,时间戳和日期格式之间可以利用from_unixtime(时间戳 ->日期)和 unix_timestamp(日期 -> 时间戳)进行转换。eg:select from_unixtime(time,'yyyy-MM-dd') as timeFrom question_practice_detail(II)时间格式变换:eg:date_format(date, "%Y-%m-%d")

2)时间截取

1. 年月日、时分秒提取

SQL提供了对应的年月日、时分秒提取函数,分别为year(返回date的年份,范围在1000到9999),month(返回date的月份,范围1到12),day,hour(返回time的小时,范围是0到23),minute(返回time的分钟,范围是0到59),second(回来time的秒数,范围是0到59)。

mysql>select year('2021-08-01'),month('2021-08-01'),day('2021-08-01')
mysql> select YEAR('98-02-03');     # 1998
mysql> select HOUR('10:05:03'),MINUTE('98-02-03 10:05:03'),SECOND('10:05:03');   #10,5,3

2. 返回名字:

DAYNAME(返回date的星期名字。)
MONTHNAME(返回date的月份名字)

mysql> select DAYNAME("1998-02-05");     # 'Thursday'
mysql> select MONTHNAME("1998-02-05");   # 'February'

3. 计算天:

DAYOFMONTH(返回date的月份中日期,在1到31范围内。)
DAYOFYEAR(返回date在一年中的日数, 在1到366范围内。)
last_day(colName):返回本月最后一天日期

mysql> select DAYOFMONTH('1998-02-03');   # 3
mysql> select DAYOFYEAR('1998-02-03');     # 34
mysql> select last_day('1998-02-03');     # 1998-02-28
mysql> select day(last_day('1998-02-03'));     # 28

4. 计算周:

  1. 星期几

DAYOFWEEK(返回日期date的星期索引(1=星期天,2=星期一,> ……7=星期六)。这些索引值对应于ODBC标准)
WEEKDAY(返回date的星期索引(0=星期一,1=星期二, ……6= 星期天))。

mysql>select DAYOFWEEK('1998-02-03')   # 3
mysql> select WEEKDAY('1997-10-04 22:23:00');    # 5
  1. 第几周:

WEEK(对于星期天是一周的第一天的地方,有一个单个参数,返回date的周数,范围在0到52)第2个参数形式WEEK()允许你指定星期是否开始于星期天或星期一。
如果第二个参数是0,星期从星期天开始,(如省略第二个参数默认为0) 如果第二个参数是1,从星期一开始。

mysql> select WEEK('1998-02-20',0);    # 7
mysql> select WEEK('1998-02-20',1);    # 8

5. 季度: QUARTER(返回date一年中的季度,范围1到4)

mysql> select QUARTER('98-04-01');    # 2

3)日期差计算

1.TIMESTAMPDIFF

TIMESTAMPDIFF(interval, time_start, time_end)可计算time_start-time_end的时间差,单位以指定的interval为准,常用可选:
SECOND 秒
MINUTE 分钟(返回秒数差除以60的整数部分)
HOUR 小时(返回秒数差除以3600的整数部分)
DAY 天数(返回秒数差除以3600*24的整数部分)
MONTH 月数
YEAR 年数

2. datedff

datediff的作用为计算两个日期之间的天数间隔,语法为datediff(date1,date2),返回
起始时间 date1 和结束时间 date2 之间的天数,date1大于date2的情况下,返回的天数为正数,date1小于date2的情况下,返回的天数为负数。

select datediff('2021-08–09','2021-08-01') #8

3. date_sub

语法为date_sub (string startdate, interval int day) ,返回开始日期startdate减少days天后的日期。

select date_sub('2021-08–09',interval 8 day)   #‘2021-08-01'

4. date_add

语法为date_add(string startdate, interval int day) ,返回开始日期startdate增加days天后的日期

select date_add('2021-08–01',interval 8 day)  #‘2021-08-09'

5. PERIOD_ADD(P,N)

P增加N个月到阶段值(以格式YYMM或YYYYMM)。以格式YYYYMM返回值。注意阶段参数P不是日期值。

mysql> select PERIOD_ADD(9801,2);     # 199803

6. PERIOD_DIFF(P1,P2)

返回在时期P1和P2之间月数,P1和P2应该以格式YYMM或YYYYMM。注意,时期参数P1和P2不是日期值。

mysql> select PERIOD_DIFF(9802,199703);        #11

4.文本函数

1)分割:substring_index

substring_index(str要处理的字符串,delim分隔符,count计数)
(1)当n大于0时取第n个分隔符(n从1开始)之后的全部内容;
(2)当n小于0时取倒数第n个分隔符(n从-1开始)之前的全部内容;
(3)截取分隔符分隔的中间字符串可用多个substring_index

substring_index(substring_index(profile, ",", -2), ",", 1)
#profile列如180cm,75kg,27,male截取27

2)替换:replace

replace(string, ‘被替换部分’,‘替换后的结果’)

select device_id, replace(blog_url,'http:/url/','') as user_name

3)截取:substr、substring

1.substr(string A,int start,int len可选参数),返回字符串A从下标start位置开始,长度为len的字符串
2.substring(string A,int start),在不指定返回字符串长度的情况下,返回字符串A从下标start位置到结尾的字符串

select substring(‘bacda’,2,2)
select substring(‘bacda’,2)

4)格式化:trim和ltrim(rtrim())

trim(‘被删除字段’ from 列名)

--select  device_id, trim('http:/url/' from blog_url) as user_name

5)定位:instr

instr(str,substr):返回substr字符串在str里第一次出现的位置,从1开始,没有则返回0。

select instr('bacd','a')
#该行代码表示从bacd字符串中寻找字符a首次出现的位置,输出值为2

6)长度:length、CHAR_LENGTH

length函数返回文本字段中值的长度,比如

select length(‘abc’)
#返回结果为3
WHERE CHAR_LENGTH(nick_name) > 10
#筛选昵称字符数大于10的用户

7)连接

(1)concat和concat_ws
CONCAT函数用于将两个或多个字符串连接起来,形成一个单一的字符串

select concat(‘abc’,'bcd’)
#返回结果为 ‘abcbcd'
select concat(‘abc’,’bcd’,’ff')
#返回结果为 ‘abcbcdff'
select concat_ws("aaa","2","3","89")

(2)group_concat,需与group by连用。通过使用distinct可以排除重复值;如果希望对结果中的值进行排序,可以使用order by子句;separator是一个字符串值,缺省为一个逗号。
语法:group_concat([distinct] 要连接的字段 [order by 排序字段 asc/desc ] [separator ‘分隔符’])

select group_concat(distinct concat(date(start_time),":",tag) order by start_time SEPARATOR ';')

8)大小写

5. 窗口函数

1)序号函数:

  • rank() over() 1 2 2 4 4 6 (计数排名,score相同跳过相同的几个,eg.没有3没有5)
  • row_number() over() 1 2 3 4 5 6 (赋予唯一排名)
  • dense_rank() over() 1 2 2 3 3 4 (score相同不跳过排名,可以理解为对类别进行计数)

1. row_number() over partition by

函数的含义为先分组再排序, row_number() over (partition by col1 order by col2),表示根据col1分组,在分组内部根据col2排序

Select device_id, university,gpa,
row_number() over (partition by university order by gpa desc) as
rank. - -desc代表降序排列
From user_profile
#上述代码含义为在每个学校的内部根据gpa进行一次排名,
获得每个学生在学校的名次数据,desc代表是按照从大到小降序排列。

2.dense_rank() over()

2) 头尾函数: first_val/ last_val/nth_value

first_val(expr) / last_val(expr)用途:得到分区中的第一个/最后一个指定参数的值。
nth_value(expr, n)用途:返回窗口中第N个expr的值,expr可以是表达式,也可以是列名
eg: nth_value(col,取第几名) over partition by
如NTH_VALUE(time_took, 2) OVER (PARTITION BY exam_id ORDER BY time_took DESC)

3) lead、lag前后函数

  • lead(字段名,n) over () :取值向后偏移n行(空间的理解就是直接将一列数据往前推n个位置,后面的位置就空出来了);
  • lag(字段名,n) over () :取值向前偏移n行(空间的理解就是直接将一列数据往前后n个位置,前面的位置就空出来了);
  • lag(字段名,n,x) over () :取值向前偏移n行,并将空值填充为数字x(空间的理解就是直接将一列数据往前后n个位置,前面的空出来的位置用X填充上)

lead后面括号里的三个参数分别是(字段名称,行数,默认值),字段名称就是,你要从后面的行里取那个字段;行数就是你要取后面的第几行数据,需要注意的是,这个字段是可以省略的,省略就等同于设为1;默认值就是如果到最后一行了,也就是没有下一行了,这个字段填什么,需要注意的是,这个字段是可以省略的,省略就等同于设为null。所以上面那段代码其实就是,取后面第一行的time字段,如果到最后一行了,这个字段就填null。

select device_id,
date,lead(date) over (partition by device_idorder by date
) toTime from question_practice_detail
#当天日期与下一天比较

用户留存题目
lead窗口函数题目

4) 分布函数:percent_rank()/cume_dist()

1.percent_rank()

用途:和之前的RANK()函数相关,每行按照如下公式进行计算:(rank - 1) / (rows - 1) 其中,rank为RANK()函数产生的序号,rows为当前窗口的记录总行数。

2.cume_dist()

用途:分组内大于等于当前rank值的行数/分组内总行数,这个函数比percen_rank使用场景更多。 应用场景:班级中比当前同学成绩高的学生比例是多少

5) 聚合函数 count() over/sum() over

如count(*) over(partition by level)
例题累计数量

6.比较函数greatest,least,max,min

取最大值最小值
greatest(col1,col2,…)
least(col1,col2,…)
max(col)
min(col)

六、限制结果集

1.组合查询

1)解析

I. 多数 SQL 查询只包含从一个或多个表中返回数据的单条 SELECT 语句。 但是,SQL 也 允许执行多个查询(多条 SELECT 语句),并将结果作为一 个查询结果集返回。这些组合查询通常称为并(union)或复合查询 (compound query)。
II. 其效果往往可以用where or 替换。
III. 使用union组合查询时,只能使用一条order by字句,他必须位于最后一条select语句之后,因为对于结果集不存在对于一部分数据进行排序,而另一部分用另一种排序规则的情况。
IV. union 和union all
union–将两个表做行拼接,同时自动删除重复的行。
union all—将两个表做行拼接,保留重复的行。

2)union

需要注意的是UNION 中的每个查询必须包含相同的列、表达式或聚集函数(不过, 各个列不需要以相同的次序列出)

3)union all

UNION 从查询结果集中自动去除了重复的行。如果想不去重的返回所有的匹配行,可使用 UNION ALL而不是UNION。

select * from user_profile
union all
select * from user

2.limit用法:

(1)LIMIT 子句可以被用于强制 SELECT 语句返回指定的记录数。
(2)LIMIT 接受一个或两个数字参数。参数必须是一个整数常量。
(3)如果只给定一个参数,它表示返回最大的记录行数目。
(4)如果给定两个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数目。
(5)为了检索从某一个偏移量到记录集的结束所有的记录行,可以指定第二个参数为 -1。
(6)初始记录行的偏移量是 0(而不是 1)。
(7)结合 limit offset
一起使用时,limit表示要取的数量,offset表示跳过的数量
select device_id from user_profile limit 2 offset 0 // 跳过0条,从第一条数据开始取,取两条数据
(8)结合OFFSET...FETCH
选取中间任意几行 :
(I)( LIMIT OFFSET)
查询第n到m行
SELECT 数据列 FROM 数据表 LIMIT m-n offset n
(II)( OFFSET...FETCH)
SELECT 数据列 FROM 数据表  OFFSET n rows   FETCH NEXT m-n rows ONLY
(9)运行效率

select device_id from user_profile limit 0,2---运行效率更高
select device_id from user_profile limit 2 ---运行效率低
select device_id from user_profile limit 2 offset 0 运行效率中

3.top

(1)SQL SERVER里可以使用。使用方式如下:
select top number/percent column(s) from user-profile;
(2)不适用于所有的数据库语言。在MySQL就不适用。在MySQL中使用的是limit。

4.eg

(1)查看前两个:

 SELECT  device_id FROM user_profile ORDER BY id LIMIT 2SELECT  device_id FROM user_profile ORDER BY id where id in(1,2)SELECT  device_id FROM user_profile ORDER BY id where id<=2

(2)检索记录行 6-10:

 SELECT * FROM table LIMIT 5,5

(3)检索记录行 11-last:

SELECT * FROM table LIMIT 10,-1

七、综合练习

1.avg(if(result=“right”,1,0))和sum(if(result=“right”,1,0))/count(1)
2.最后加一个with rollup汇总
coalesce函数和with rollup计算聚合函数求和

八、效率:

1.like

模糊查询会引起全表扫描,速度比较慢,应该尽量避免使用like关键字进行模糊查询。

2.limit

select device_id from user_profile limit 0,2---运行效率更高
select device_id from user_profile limit 2 ---运行效率低
select device_id from user_profile limit 2 offset 0 运行效率中

3.with as

with as

总结

提示:这里对文章进行总结:

例如:以上就是要讲的内容,

SQL2022-8-10相关推荐

  1. H3CNE最新版官网考试模拟题库

    以下工作于OSI 参考模型数据链路层的设备是__A____.(选择一项或多项) A. 广域网交换机 B. 路由器 C. 中继器 D. 集线器 A 数据链路层传输的是帧,交换机是基于帧转发的:B 路由器 ...

  2. lisp协议instand_分享|Linux 上 10 个最好的 Markdown 编辑器

    在这篇文章中,我们会点评一些可以在 Linux 上安装使用的最好的 Markdown 编辑器. 你可以在 Linux 平台上找到非常多的 的 Markdown 编辑器,但是在这里我们将尽可能地为您推荐 ...

  3. 10任务栏全屏时老是弹出_Deepin 15.10 发布,深度操作系统

    深度操作系统是一个致力于为全球用户提供美观易用.安全可靠的Linux发行版. 深度操作系统基于Linux内核,以桌面应用为主的开源GNU/Linux操作系统,支持笔记本.台式机和一体机.深度操作系统( ...

  4. Linux shell 学习笔记(10)— 处理用户输入(命令行读取参数、读取用户输入、超时处理)

    1. 命令行参数 向 shell 脚本传递数据的最基本方法是使用命令行参数.命令行参数允许在运行脚本时向命令行添加数据. $ ./addem 10 30 本例向脚本 addem 传递了两个命令行参数( ...

  5. Anaconda3+python3.7.10+TensorFlow2.3.0+PyQt5环境搭建

    Anaconda3+python3.7.10+TensorFlow2.3.0+PyQt5环境搭建 一.Anaconda 创建 python3.7环境 1.进入 C:\Users\用户名 目录下,找到 ...

  6. debian 10 静态ip配置

    查看网卡 ip addr 修改配置 vim /etc/network/interfaces 模板 auto ${网卡名} iface ${网卡名} inet ${static} address ${I ...

  7. 解决 win10 pycurl安装出错 Command python setup.py egg_info failed with error code 10 编译安装包 安装万金油...

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/yexiaohhjk/article/d ...

  8. 英特尔Intel® Arria® 10 FPGA加速器设计

    英特尔Intel® Arria® 10 FPGA加速器设计 Introducing the Intel® Vision Accelerator Design with Intel® Arria® 10 ...

  9. 保护嵌入式802.11 Wi-Fi设备时需要考虑的10件事

    保护嵌入式802.11 Wi-Fi设备时需要考虑的10件事 10 things to consider when securing an embedded 802.11 Wi-Fi device 随着 ...

  10. 交换机应用寻找10个完美的因素

    交换机应用寻找10个完美的因素 10 factors for finding the perfect switch for your application 选择开关的过程并不总是值得注意的.考虑到大 ...

最新文章

  1. JAVA_day2_运算符
  2. 表格过滤器_气缸选型其实并不复杂,知道这些再也不怕选错气缸(附计算表格)...
  3. 在新版本caffe里添加新的一层(向旧格式中加)
  4. 使用python标准库urllib2访问网页
  5. [转载] Java异常处理中Try-Catch-Finally中常见的笔试题
  6. 【python】命令行参数argparse用法详解
  7. zuul压力测试与调优
  8. C3模块-空洞可分离卷积存在的问题及轻量化语义分割模型架构技巧
  9. 关于ISIS协议TLV TAG标签的研究与简单实验
  10. 用Poedit翻译wordpress主题或插件的步骤
  11. 小记: 程序设计注意保持逻辑清晰
  12. 2022最推荐的四款免费bi工具
  13. 网络带宽 (网速) 在线测试
  14. 嵌入式分享合集118
  15. Android 构建简单app 步骤
  16. mongodb安装及操作
  17. web渗透测试实战-SQLMAP
  18. mysql中flush用法,flush 的常规用法:
  19. VSCode更改主题背景
  20. 双飞燕G3-200N鼠标修理

热门文章

  1. Go设置、获取cookie
  2. 常见Oracle错误都在这了: ORA-00257/ORA-00313/ORA-28000/ORA-28000
  3. 面试:Jetpack相关
  4. Servlet学习记录3
  5. 说一下我对并发数、吞吐量的理解
  6. 一丶脚本的下载与安装
  7. Android 解决 adapter.notifyDataSetChanged() 不起作用
  8. CCF-CSP 小中大 C语言
  9. 在以太坊开发自己的ERC-20代币及如何ICO
  10. php json输出对象的属性值,JavaScript_jquery动态遍历Json对象的属性和值的方法,1、遍历 json 对象的属性/ - phpStudy...