牛客网 sql在线编程 常用到的函数统计(持续更新)

本文只是为了记录下刷sql试题的时候,所用到的一些sql函数及注意事项,知识点比较零碎,如果看官想进一步了解其用法,可能还要自行去百度一下;

 #sql中关键字出现的顺序是:
select/from/where/group by/having/order by/limit

1.distinct 

distinct # 得到不重复的值

2. limit 

#注意:查询到的记录默认从0开始编号,而sql字符串默认从1开始编号;要注意两者的区别
select * from user limit i,n; # 从索引i处开始查找,返回n条查询结果
select * from user limit n; # 返回n条查询结果

3. between and 

# 查找年龄在[20,23]之间的设备号,性别,年龄
select device_id,gender,age from user_profile where age between 20 and 23; 

4. 不等号 

# 不等号
select device_id,gender,age,university from user_profile where age <> "";
select device_id,gender,age,university from user_profile where university!="复旦大学";

5.  属性值为字符串的判断表示法

# 对某个属性值的字符串判断的错误写法
select device_id,gender,age,university,gpa from user_profile where gpa >3.5 and gender is "male";
# 正确写法
select device_id,gender,age,university,gpa from user_profile where gpa >3.5 and gender = "male";

6. 或  or

# 或
select device_id,gender,age,university,gpa 
from user_profile 
where university="北京大学" or gpa > 3.7

7. in 

# in
select device_id,gender,age,university,gpa from user_profile where university in ("北京大学","复旦大学","山东大学");

8.  操作符的混合使用

# 操作符的混合使用
select device_id,gender,age,university,gpa from user_profile
where (gpa > 3.5 and university = "山东大学") or (gpa > 3.8 and university = "复旦大学");

 9. like % _

# like
# %:0个或多个字符
# _:1个字符
select device_id,age,university from user_profile where university like '%北京%';

 10. max

# max
select max(gpa) from user_profile where university = "复旦大学";

11. count avg 

# count avg
select count(gender),avg(gpa) from user_profile where gender="male";

 12. group by a,b,c...及正确的表示法

# group by a,b,c,...  可以多个属性值为一组,来进行分组,一组对应多个符合条件的值
# 注意:没有这种写法:group by (a,b,c,...)
select gender,university,count(id),avg(active_days_within_30),avg(question_cnt) from user_profile group by gender,university;
# 下面这种写法是不对的
select gender,university,count(id),avg(active_days_within_30),avg(question_cnt) from user_profile group by (gender,university);

13. having 

# 分组后选取符合条件的值用having
# 取出平均发贴数低于5的学校或平均回帖数小于20的学校
select university,avg(question_cnt) as avg_question_cnt,avg(answer_cnt) as avg_answer_cnt 
from user_profile 
group by university 
having avg_question_cnt < 5 or avg_answer_cnt < 20;
# 错误写法1  既然分组了,对分组后得到的值按要求取舍,只能用having,不能用where
select university,avg(question_cnt),avg(answer_cnt) from user_profile where avg(question_cnt) < 5 or avg(answer_cnt) < 20 group by university;
# 错误写法2   把聚合函数得到的值作为新的列名,再根据新的列名查找
select university,avg(question_cnt),avg(answer_cnt) from user_profile group by university having avg(question_cnt) < 5 or avg(answer_cnt) < 20;

14. order by 

# order by 在 group by 之后
# asc 升序(默认) desc 降序
select university,avg(question_cnt) as avg_question_cnt 
from user_profile 
group by university
order by avg_question_cnt;

15. A left join B on 条件 

# A left join B on 条件 :将属性值与A表相匹配的B表插入到A表上
select question_practice_detail.device_id,question_practice_detail.question_id,question_practice_detail.result 
from question_practice_detail left join user_profile 
on  question_practice_detail.device_id = user_profile.device_id
where user_profile.university = "浙江大学"
order by question_practice_detail.question_id;

16.  保留小数点后n位

# 保留小数点后n为
round(x,n)

 17. 统计数据表中数据的行数

# 统计表中数据的行数
count(*)

18. union all   与 union 的区别

# 将2个sql语句查询到的结果(A,B)给合并起来,结果不去重,保留重复的行
A union all B
# 比如
select device_id,gender,age,gpa from user_profile where university = "山东大学"
union all
select device_id,gender,age,gpa from user_profile where gender = "male";

# union 结果去重,不保留重复的行

19. if语句 

# sql if语句
# if(condition,A,B) 如果符合条件就取值A,否则取值B
select 
    if(age >= 25,"25岁及以上","25岁以下") as age_cut,count(*) 
    from user_profile group by age_cut;

20. case语句 

# case 语句
select device_id,gender,
    case
        when age < 20 then "20岁以下"
        when age between 20 and 24 then "20-24岁"
        when age >= 25 then "25岁及以上"
        else "其他"
    end
    as age_cut
from user_profile;

21. 日期函数 

# 日期
# day(date) 日期中当月的第几天
# month(date) 日期中的月份
# year(date) 日期中的年份
select day(date) as day,count(*) as question_cnt 
from question_practice_detail 
where month(date) = 8 
group by day;

22. 日期差 

# datediff(date2,date1) 日期差

23. substring_index(str,delim,count)  

# substring_index(str,delim,count) 根据分隔符在字符串中的位置,来返回分隔符最左边或最右边的所有内容
# str 源字符串 delim 分隔符 count 第几个分隔符
#count > 0:从左往右数,第count个分割符的左边的所有内容
#count < 0:从右往左数,第coun个分隔符的右边的所有内容
############################
# profile:180cm,75kg,27,male
select substring_index(profile,',',-1) as gender,count(device_id) as number 
from user_submit
group by gender;

24. substring(str,start,len) 

# 截取字符串
substring(str,start,len) 字符串的索引编号默认从1开始 从字符串str的start位置开始,截取长度为len的字符串

25. sum与if的结合 

# sum 与 if 的结合使用
sum(if(result = "right",1,0))

26.  count(column)   count(a,if(b_condition,true,null))   count(a_condition or null)

# count(column) 具有自动忽略空值的功能,即对column中值为空的不计数
# count(a,if(b_condition,true,null)) if中的b不能与a相同,否则会报错;这个公式根据b的值来统计a的数目
# 注意:count 与 if相结合使用的时候,空值只能用null表示,不能用0
# count(a_condition or null) 根据a的自身条件来统计 
################################################
# 现在运营想要了解2021年8月份所有练习过题目的总用户数和练习过题目的总次数
select count(distinct device_id,if(result is not null,TRUE,null)) did_cnt,
count(result is not null or null) question_cnt
from question_practice_detail
where year(date) = '2021' and month(date) = '8';

 27. group_concat()

# group_concat()  将分组后指定的属性值用分隔符进行连接 分隔符默认为","
# 分割符指定的时候需要加关键字 separator
select university,group_concat(distinct age separator ",") age_concat
from user_profile
group by university;

28.  concat(str1,str2,....)

# 字符串拼接,str1 + str2
concat(str1,str2,...)

29. 按指定顺序返回

# 按"下旬,中旬,上旬"的顺序进行排序
order by locate(substr(dt_range,9,2),"下旬,中旬,上旬")

30. date_format(date,format) 日期的格式化

# date_format(date,format) 日期的格式化
date_format(event_date,"%Y年%m月")

31. 字符长度 字节长度

# 字符长度 char_length(str) 汉字、字母、数字都算一个字符
# 字节长度 length(str) utf8,汉字3个字节;gbk汉字2个字节
#######################################
# 注意:不能用nick_len作为where判断的条件
select device_id,nick_name,char_length(nick_name) nick_len
from user_submit
where char_length(nick_name) > 4
order by device_id desc;

32. upper(str)  lower(str) 字符串大小写转换

upper(str) 转大写字母
lower(str) 转小写字母

33. trim(str) 去两边空格

trim(str) 去左右两边的空格

34. reverse(str) 反置字符串

# 反置字符串
reverse(str)

35. with as 用法

# with as 用于提前将连接操作从主函数中分离出来,以使逻辑更加清晰
# 2种写法:
# with name as (...)
# with as (...) name
with q as (select device_id,date_format(event_date,"%Y-%m") new_date,count(*) cnt
        from question_practice_detail
        group by device_id,date_format(event_date,"%Y-%m")
        having count(*) > 1)
select distinct q1.device_id
from q q1 left join q q2 on q1.device_id = q2.device_id
# 多个别名
with name1 as (...),
    name2 as (...),
    name3 as (...),
    ...
#注意:以下这种写法不对
with name1 as (...)
with name2 as (...)
with name3 as (...)

36. left join、right join、inner join

参考博客

A left join B on condition  #以A表为基准,用B的信息进行填补
A right join B on condition  #以B表为基准,用A的信息进行填补
A inner join B on condition  #以condition为基准,取AB两表共有的
# 当多个表使用inner join的时候,要尽量把属性列多的那个表放在最左边

37.插入语句 insert into table_name values(,,,)

insert into table_name (columns1,columns2,...) values (v1,v2,...)

insert into table_name set c = v1,c = v2,... 

insert into table_name select * from table_name2

参考

# 插入语句 空值用null 自增值auto_increment用default填补
insert into table_name values (,,,) #插入的值的顺序要严格按照定义时的顺序一致
# 指定列名来插入值
insert into table_name (column_name1,column_name2,column_name3,...) values (v1,v2,v3,...)
# 或
insert into table_name set column_name1 = v1,column_name2 = v2,column_name3 = v3,....
# 将查询到的数据插入到一个表中
insert into table_name select * from table_name2 # table_name为要插入的表,table_name2为要查询的表,需保证查询出来的值要与table_name中预定义的属性值的顺序一致
# 若要将select查询到的指定数值插入
insert into new_table (column1,column2,...) select (column1,column2,...) from table where..

 38. date_add(date,interval num type) 与date_sub(date,interval num type)日期间隔

参考

# 求日期间隔
date_add(date,interval 3 day) # 在date1的基础上,增加3天
# day是间隔单位,还可取值second,minute,year,month,hour,week等
date_sub(date,interval 3 day) # 在date1的基础上,减去3天

39. insert into/insert ignore into/replace into 当插入遇到重复的键值

参考

# 具体用法与37类似,这里只讲操作的大致原理
# 插入一行数据,若主键已存在,则会报错,否则,直接插入
insert into 
# 插入一行数据,若主键已存在,则新的数据替代原来的数据(先删除再插入),否则,直接插入
replace into
# 插入一行数据,若主键已存在,则不插入,否则,直接插入
insert ignore into

40. update table_name set column1 = v1,column2 = v2... where 更新表中的某个属性值

# 更新属性值
update table_name set column1 = v1,column2 = v2... where ...

41. delete from table_name where... 删除表中的指定记录

delete from table_name where ...

42. timestampdiff(type,start,end)  求时间差,单位为type

# type取值与38类似
# end-start的单位为type的一个时间差
timestampdiff(type,start,end)

 43. ifnull(exp,a) 

# exp不为null,则返回exp的值,否则返回b;
# exp可以为一个条件表达式,也可以为一个字符串或数字等等
ifnull(exp,b)

44. truncate table table_name 删除记录,并重置自增键值

# 删除表中的记录并重置自增主键的索引
truncate table table_name
# 或
truncate table_name

45. 创建一个新表

参考

create table if not exists table_name(
        column_name type # 字段名,类型
        primary key # 主键
        foreign key # 外键
        auto_increment #自增
        comment "name" # 列注释
        default value # 默认值
        unique # 唯一约束,同列不允许有相同的值;解决表中多个字段需要唯一性约束的问题;允许多个空值
        not null #非空,默认为空
) default charset = "" # 编码形式

 46. 修改/删除/增加表中的字段名

参考

alter table table_name add column column_name type # 增加字段名
alter table table_name drop column column_name type # 删除字段名
alter table table_name modify column column_name type # 修改字段类型
alter table table_name change column column_name new_column_name type # 修改字段名
# 在指定的字段名后添加一个新的字段,假如新字段名为new_column 指定的字段为specified_column
alter table table_name add new_column type after specified_column
# 注意:不管修改什么,type均不能少,否则会报错

47. 修改表名

alter table old_table_name rename to new_table_name

48.  删除表

drop table table_name

49. 创建索引

# 创建索引的基本语法
create index_mode index index_name on table_name(column_name)
# index_mode:空值 普通索引,索引值可重复
#            unique 唯一索引,索引值不可重复,可有多个空值
#            fulltext 全文索引,在给定的列中存储有关重要的词及位置信息,一种特殊类型的基于标记的功能性索引             

50. 删除索引

# method 1
drop index index_name on table_name;
# method 2
alter table table_name drop index index_name;

51. 求当月的天数,当月有几天

last_day(date) #当月有几天

52. any_value()

MySQL提供了any_value()函数来抑制ONLY_FULL_GROUP_BY值被拒绝。
所以只需要在非group by的列上加any_value()就可以了

53. union 与 order by 的正确结合使用

# 当order by出现在union的子句中,order by会失效
# 比如:以下得到的结果并不是上表与下标都排序好,再连接到一起的;它们虽然连接到了一起,虽然各排各的,最后再连接,但并不是排序好的
# 因为order by 出现在 union的子句中,排序会失效
(select exam_id tid,count(distinct uid) uv,count(*) pv 
from exam_record
group by exam_id
order by uv desc,pv desc)
union
(select question_id tid,count(distinct uid) uv,count(*) pv
from practice_record
group by question_id
order by uv desc,pv desc)
###############################################
# 要想使order by与union一起使用时,使得order by生效,那么要把order by放在union的子句的子句中
# a,b两个表名不可少
select * from
(select exam_id tid,count(distinct uid) uv,count(*) pv 
from exam_record
group by exam_id
order by uv desc,pv desc)a
union
select  * from
(select question_id tid,count(distinct uid) uv,count(*) pv
from practice_record
group by question_id
order by uv desc,pv desc)b
###############################################
##### 综上 #####
## 如果想要对未union前两个sql语句的查询结果进行排序,分别单独排序需要的数据,查出以后再使用union连接
select * from
( select * from t1  order by 字段 )t1 -- 一定要对表重新命名,否则报错 
union select * from
( select * from t2  order by 字段 )t2

54. 左右连接时,要考虑出现重复行

# 左连接时,当右表连接到左表,当左表的一个值对应右表的多个值的时候;
# 要考虑到左表出现重复行的情况 
# 当右表多个值对应左表多个值时,要考虑到连接后的左右表出现重复行的情况
# 还要考虑每个记录表中的提交时间可能会重复的情况

猜你喜欢

转载自blog.csdn.net/power_kaikaige/article/details/126173662