1-MySQL基础和查询一些特殊业务需求和技巧

在进行复杂业务逻辑sql编写时,往往理不清多张表之间的连接关系,这时你需要一个清晰的思路来串连多张表。第一个误区就是根据查询条件认为查询字段所在表为主表,这是错误的,表的连接顺序往往是固定的,查询条件字段所在表是主表是个伪命题。

 

1、根据某个字段分组,但是字段值为某些值得是有归为一组

比如记录如下:
id status
100 1
101 2
102 3
103 4
104 5
105 99
106 98
将status 5 99 98的归为一个组,其他的按status值分组
SELECT
    count(*) as count,
    case when status in (90,98,5) then 5 else status end as optyStatus
from some_test
where `status` is not null
group by case when status in (90,98,5) then 5 else status end

2、2个表间复制数据

INSERT INTO hb_t_nickname1(nickname,gender,is_deleted)
SELECT DISTINCT nickname,gender,is_deleted FROM hb_t_nickname;

3、删除重复数据

注意:不能重命名

DELETE hb_t_iu from hb_t_iu,(

SELECT
    max(id) id,
    tel
FROM
    hb_t_iu
GROUP BY
    tel    
HAVING
    count( * ) > 1 ) iu2
where hb_t_iu.tel = iu2.tel
and hb_t_iu.id < iu2.id

4、连表更新

UPDATE huc_user huser
inner join hb_t_iu iu on huser.mobile_no = iu.tel
SET huser.gender = iu.gender

5、取余数

mod(m,n)
m是被取余的数,n是模

6、计算datetime类型日期和当前时间天数

TIMESTAMPDIFF(YEAR, huser.birth_time, now())

需要注意的是,两个日期之间的位置和计算规则,第一个时间是beginTime,后一个是endTime,beginTime数值上要比endTime小,否则会出现负数,第一个参数是Unit,取值可以有:

MICROSECOND 微秒
SECOND  秒
MINUTE  分钟
HOUR   小时
DAY   天
WEEK  星期
MONTH  月
QUARTER  季度
YEAR  年

7、Navicate导出数据时某个字段被处理成无规则串?

查看这个字段类型,longtext有这种情况,使用cast(field as char)转换一下即可。

8、mysql between and使用

between and 的左右边界是闭合的,但是在处理时间时需要注意,如果是datetime类型,且入参没有时间时,时间默认为00:00:00,如:

select * from t_x where created_time between '2020-01-01' and '2020-01-01';

这样两个时间都会是2020-01-01 00:00:00,这样很可能跟你的预期不符合。

9 trur flase含义

mysql中boolean用tinyint(1)实现,true=1,false=2

select true + 1 // 2

10 mysql varchar 和int比较

2ABC3 =2 // true

2abc > 1 // true

mysql会把字符串类型转换成数字,从第一个字符开始解析,到第一个字符不符合结束

 

11 count()和sum()

count(expression) 函数,注意入参是表达式

sum(expression) 函数,入参也是表达式

count(*)=count(1) // 统计行数,不管字段是否为空

count(field) // 字段为null的会被排除,空串和空白字符依然被计算

sum(field) // 数值类型没什么,如果field是varchar,如果存了实数也没什么,如果存了非实数字符串,会被解析成0

sum(2) // 是每一列都是2来相加

sum(field=2) // 表达式成立就是true也即1

count(var=2) // 表达式没有意义了,true或false结果都一样

12 汇总

select ifnull(a,汇总),count(*) group by a with rollup // 就是汇总

13 一对多连接去重

怎么处理?

14 查询表的所有字段

show full columns from t;

15 查询一张表所有字段饱和度?

16 group by 没有的字段需要返回?

当查询简单时,可以通过构建临时表完成如:select x union select y union select z构建一个临时结果作为主表,但是关联的表过多时,比如需要通过能关联上另一张表作为选中的结果并计算合计,这样就很难操作了,只能在Java中操作,如何操作,定义一个final List,然后遍历,将查询结果集转换成map,然后构建一个新List返回,这样即可以填充没有的字段,还能保证顺序,其中List转Map需要我们掌握。

17 编码选择

2、关于字段编码选择,有个同事建立的某张表使用了不同的字符编码,导致大小写敏感了,相关字段索引也无法使用。mysql字符集默认的编码查询:show charset;

如果指定了表的字符集,那么字段的字符编码就是默认的了,其中utf8mb4_bin大小写敏感,使用时注意。

18 date_format()的迷惑点

select DATE_FORMAT('2020-09','%Y-%m') // 输出null

这种用法有可能出现在前端传参和已有字段比较的情况,为什么输出null,因为date_format接受的第一个参数类型是date,至少要有年月日,这里只有年月,不被认为是日期,所以格式化无效,直接输出null,使用的时候需要警惕。

19 MySQL数据库约束

约束(constraint),使用来保证数据库中数据完整性(实体完整性(Entity Integrity)、域完整性(Domain Integrity)、参照完整性(Referential Integrity)、用户定义的完整性(User-definedIntegrity))的手段之一。

MySQL中常用的约束:

约束类型: 主键 外键 唯一 非空 自增 默认值
关键字: primary key foreign key

unique

not null

auto_increment

default

primary key = unique + not null

使用方式如下:

ALTER TABLE `zz` ADD PRIMARY KEY ( `id` ) // 添加主键,不需要给主键起名字

ALTER TABLE `zz` DROP PRIMARY KEY // 删主键,主键不需要名称,因为只有一个,此字段不能有自增属性,否则删不了。

ALTER TABLE zz ADD CONSTRAINT fk_prod_id FOREIGN KEY (product_id) REFERENCES product (id); // 添加外键

ALTER TABLE `zz` DROP FOREIGN KEY `fk_prod_id`; // 删除外键

ALTER TABLE zz ADD UNIQUE KEY uk_2(name,product_id); // 添加唯一约束

ALTER TABLE zz ADD UNIQUE uk_2 (NAME, product_id); // 添加唯一约束可以省略 KEY关键字

ALTER TABLE zz ADD CONSTRAINT UNIQUE uk_2 (NAME, product_id); // 添加唯一约束多加一个constraint关键字也行

ALTER TABLE zz DROP INDEX uk_2; // 删除唯一约束,注意这里已经变成index了

ALTER TABLE zz MODIFY product_id VARCHAR (12) NOT NULL; // 添加非空约束

ALTER TABLE zz MODIFY product_id VARCHAR (12) NULL; // 删除非空约束

MySQL表中只能设置一个自增长字段【必须是key(其他普通字段不行))】

ALTER TABLE zz MODIFY product_id INT UNSIGNED AUTO_INCREMENT; // 添加自增

ALTER TABLE zz MODIFY product_id INT UNSIGNED;// 删除自增

20 常用表结构修改

修改字段编码使支持emoji表情

ALTER TABLE t_user MODIFY `signature` VARCHAR(255) CHARACTER SET utf8mb4 DEFAULT NULL  COMMENT '';

添加单个或多个字段索引

ALTER TABLE table_name ADD INDEX index_name (column_list)
ALTER TABLE table_name ADD UNIQUE (column_list)
ALTER TABLE table_name ADD PRIMARY KEY (column_list)

主键一定是索引,索引未必是主键,复合主键一定建立复合索引,复合主键不能重复,每个键都不能为空。

联合主键:指多张表的主键组合,多半出现在多对多时的中间表上

复合主键:一张表中多个字段组成primary key,一张表只能有一个主键,主键分为单一主键和复合主键

添加字段

ALTER TABLE xxx_yy ADD terminal_type tinyint (2) unsigned DEFAULT '0' COMMENT '注释';

21 case when 2种用法

-- 简单case函数
case sex
  when '1' then '男'
  when '2' then '女’
  else '其他' end
-- case搜索函数
case when sex = '1' then '男'
     when sex = '2' then '女'
     else '其他' end

需要注意的是case when搜索函数和 else if功效一样,当前的满足了,就不会进行下面的判断了,使用时需要注意这一点。

 

22 关于连接

1 连接基础

left join = left outer join

right join = right outer join

inner join = join

full join  = full outer join(left join + right join)

对于left join,条件写在on后面和where后面是有区别的,写在on后的不会影响主表记录,哪怕条件是关于主表的,写在where后面的条件是针对连接后的结果集,可以影响到主表记录。如:

SELECT
	u.NAME,
	ur.role_id
FROM
	user_cn u
LEFT JOIN user_role ur ON u.id = ur.user_id AND u.NAME = '张飞' // 这里的u条件不会影响主表

2 多表连接

SELECT
	u. NAME,
	r.role_name
FROM
	user_cn u
LEFT JOIN user_role ur ON u.id = ur.user_id
INNER JOIN role r ON ur.role_id = r.id

可以看到,多表连接后,如果有left join和inner join同时出现,那么inner join的排除效果就会体现到主表上了,连接顺序对结果是没有影响的,我们可以看成是inner join和前面所有连接结果再进行运算,那么自然就会排除。看这种复杂连接关系,可以先分清对应关系,这里u对ur是一对多(u和ur是多对多),ur对r是一对一。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章