sql学习笔记

sql学习笔记

sql

select

  1. distinct 去除state字段的重复项
SELECT DISTINCT state FROM customers; 
  1. between a and b >=a <=b 包含临界值

  2. WHERE name LIKE ‘b%’ 获取name值为b开头的任意长度的字符串 不区分大小写 ‘%b%’字符串中间有b ‘_b’ 下划线代表一个字符 '__y’代表三个字符最后一个是y _代表一个任意字符

  3. WHERE name REGEXP ‘filed’ ;包含filed的所有。 ‘^filed’以filed开头的所有 ‘filed$’ 以结尾的所有

    WHERE name REGEXP ‘dile|filed’ 包含dile或者filed的所有

    ‘[gim]e’ 搜索的ge 或者 ie 或者me ‘[a-h]e’ 搜索 e前面含有a-h 的所有

  4. IS NULL WHERE name IS NULL 获取名字为null的数据 IS NOT NULL

连接

  1. INNER JOIN

    SELECT * FROM atable a JOIN btable b ON a.id = b.id;
    
  2. 自连接 同一张表

    SELECT * from employee e JOIN employee m ON e.reports_to = m.employee_id; 
    
  3. 多表连接

    SELECT pa.payment_id,cl.`name`,pam.`name` AS 'payment method',date,amount FROM payments pa
    JOIN clients cl 
    ON pa.client_id = cl.client_id
    JOIN payment_methods pam
    ON pa.payment_method = pam.payment_method_id ;
    
  4. ​ 外连接 LEFT JOIN RIGHT JOIN

    LEFT JOIN 返回所有左表的结果 就是from a 不管 on这个连接条件

  5. 多表外连接

    SELECT ord.order_date,ord.order_id,cus.first_name,shi.`name` AS shipper,os.`name` AS status
    FROM orders ord
    JOIN customers cus ON ord.customer_id = cus.customer_id
    LEFT JOIN shippers shi ON ord.shipper_id = shi.shipper_id
    JOIN order_statuses os ON ord.`status` = os.order_status_id;
    
  6. USING 如果 是 ON a.name = b.name 可以使用 USING (name) 代替

  7. UNION联合 可以将两个select语句返回结果联合到一起

    SELECT a.name , 'Active' AS status FROM atable a 
    UNION
    SELECT b.name , 'Archived' AS status FROM btable b ;
    

    列属性 增加更改

    1. 多列增加

      INSERT INTO shippers (name) VALUES('haha'),('shipper1'),('shipper2')
      
    2. 表复制(存档) 不会保留主键信息 不会自增

      CREATE TABLE atable_archived AS SELECT * FROM atable 
      

      子查询插入数据

      INSERT INTO oreder_archived 
      SELECT * FROM orders WHERE order_date <'2019-01-01'
      

    聚合函数

    1. sum() avg() max() min() count(*)

    2. group by dept 根据dept进行分组

    3. having 过滤组 可放于group by后面

      SELECT pa.date,pm.`name` AS payment_method,sum(pa.amount) AS total_payment 
      FROM payments pa
      JOIN payment_methods pm 
      ON pa.payment_method = pm.payment_method_id
      GROUP BY pa.date , pm.`name` 
      
    4. WITH ROLLOP 使用在分组之后对数据进行汇总

复杂查询

  1. All 关键字 可以让where sum > ALL (110,112,203) 如果sum大于所有的数则返回在结果集中

  2. ANY关键字 和in一样 where id in (1,2,3) where id = ANY(1,2,3)

  3. 相关查询 查询员工表中高于部门平均工资的人

    SELECT * FROM employees e
    WHERE salary >(
    	SELECT AVG(salary) 
      FROM employees 
    	WHERE office_id = e.office_id
    )
    
  4. EXISTS 运算符 where id in (子查询) 子查询返回一个结果列表然后判断id where exists (子查询) 不会返回一个大的结果列表而是直接一条一条进行判断,性能更好

  5. 子查询 SELECT

    SELECT 
    	client_id,
    	name,
    	(SELECT SUM(invoice_total)
    	FROM invoices 
    	where	client_id = cli.client_id) AS total_sales,
    (SELECT AVG(invoice_total)FROM invoices ) AS average ,
    (SELECT total_sales -  average) AS difference 
    FROM clients cli
    
  6. 子查询写到form后 可以将5作为一张表再次进行筛选

触发器

mysql触发器中, NEW关键字,和 MS SQL Server 中的 INSERTED 和 DELETED 类似,MySQL 中定义了 NEW 和 OLD,用来表示触发器的所在表中,触发了触发器的那一行数据。

具体地:
在 INSERT 型触发器中,NEW 用来表示将要(BEFORE)或已经(AFTER)插入的新数据;
在 UPDATE 型触发器中,OLD 用来表示将要或已经被修改的原数据,NEW 用来表示将要或已经修改为的新数据;
在 DELETE 型触发器中,OLD 用来表示将要或已经被删除的原数据;
使用方法: NEW.columnName (columnName 为相应数据表某一列名)
另外,OLD 是只读的,而 NEW 则可以在触发器中使用 SET 赋值,这样不会再次触发触发器,造成循环调用。

 DELIMITER %%

CREATE TRIGGER payments_after_delete
	AFTER DELETE ON payments
	FOR EACH ROW
BEGIN
	UPDATE invoices SET payment_total = payment_total - OLD.amount
	WHERE invoice_id = OLD.invoice_id;
END %%

DELIMITER ;

SHOW TRIGGERS 查看所有触发器

还可以用来审计,就是将某人对数据库的操作记录下来

事件

每隔多久执行一次,

DELIMITER %%

CREATE EVENT yearly_delete_stale_audit_rows
ON SCHEDULE 
	EVERY 1 YEAR STARTS '2019-01-01' ENDS '2029-01-01'
DO BEGIN

END %%

DELIMITER ;

SHOW EVENTS; 查看事件

drop event if exists

事务

  1. ACID Atomicity 原子性 Consistency 一致性 isolation 隔离性 Durability 持久性
  2. 事务隔离级别 四个级别和常见并发问题
    1. 读未提交 , 读已提交 , 可重复读(确保不同的读取下返回同一个值) , 序列化
    2. 脏读:事务A读到了事务B未提交的数据。解决:读已提交
    3. 不可重复读:读取了相同数据俩次得到了不同的值。解决:可重复读
    4. 幻读:事务a读取符合条件的人员表,其它事务刚好执行某个操作导致有一个人不满足条件,但执行完又满足。或者刚好当事务a读取之后又插入一条。解决:系列化,在事务a读取时其它对该表的操作都会被事务a知道

数据类型

  1. string type

    • char() 存储固定长度的字符串 char(10) mysql会保留30个字节 因为字母1个字节 中文3个字节。char(4) 最大为四个字符,检测到char值尾部空格会被删除,实际大小以固定,不到四个字符会填充空格。

    • varchar 可变长度字符串 最大 0到65535 . 实际占用空间大小为字符串实际长度+1(字符串结束符) 保存和查找时尾部空格被保留。

  2. integers 整形

    • TINYINT 1字节 -128-127数值 状态
    • UNSIGNED TINYINT [0,255] 年龄
    • int 4b
  3. 定点数和浮点数

    • DECIMAL(9,2) -->1234567.89
  4. 布尔型

    • BOOL TRUE OR FALSE
  5. TIME

    • TIMESTAMP 4b 2038年之前的时间
    • DATETIME 8b
  6. BLOB

    • 存储二进制数据
    • tinyBlob 255b
    • blob 65kb
    • mediumblob 16mb
    • longblob 4gb

数据库模型设计

  1. 概念模型 --》逻辑模型–》实体模型
  2. 第一范式 : 数据表的每一列都应该是单一的
  3. 第二范式 :数据表的每一列都应该描述这个实体
  4. 第三范式 : 表中列不能是表中其它列的派生列

索引

EXPLAIN SELECT customer_id FROM customers WHERE state = 'CA';

CREATE INDEX idx_state ON customers (state);


EXPLAIN SELECT customer_id FROM customers WHERE points >1000;

CREATE INDEX idx_point ON customers (points);
  1. 前缀索引:只对字符串的前几个字符进行索引

  2. 全文索引:create fulltext index where Match(title,body) against('name haha ')

    where Match(title,body) against('name -haha +body ‘’this a name‘’ ’ in boolean mode)有name或者body但是没有haha 准确包含this a name

  3. 复合索引:CREATE INDEX idx_state ON customers (state,points); 定位state有points


IN 和 EXISTS 区别

SELECT * FROM atable WHERE id in (SELECT id FROM btable)
SELECT * FROM atable a WHERE EXISTS (SELECT id FROM btable b WHERE a.id = b.id)
SELECT * FROM customers c WHERE 
EXISTS(SELECT 1 from orders o WHERE customer_id in (1,2,3) );

IN 会用a表的每一行id与b表所有id逐个比较,
EXISTS 用a表id 去执行类似SELECT 1 FROM btable WHERE a.id = b.id;这样只是执行a表length次
感觉就是用a表的每一行去执行括号内的子查询

  • IN 适合于外表大而内表小的情况;
  • EXISTS 适合于外表小而内表大的情况。

https://leetcode-cn.com/problems/swap-salary/comments/
update salary set sex = (case sex when ‘m’ then ‘f’ else ‘m’ end);
update salary set sex = if(sex = ‘m’,‘f’,‘m’)
case用法: case a when cond1 then exp1 else cond2 then exp2 else exp3
当a满足条件cond1时, 返回exp1 当a满足条件cond2时, 返回exp2 否则 返回exp3


牛客https://www.nowcoder.com/practice/b9068bfe5df74276bd015b9729eec4bf?tpId=82&tags=&title=&difficulty=0&judgeStatus=0&rp=1
-- rank排名:查询表中大于自己薪水的员工的数量(考虑并列:去重)
SELECT 
  s1.emp_no,
  s1.salary,
  (SELECT 
    COUNT(DISTINCT s2.salary) 
  FROM
    salaries s2 
  WHERE s2.to_date = '9999-01-01' 
    AND s2.salary >= s1.salary) AS `rank`  -- 去重:计算并列排名
FROM
  salaries s1 
WHERE s1.to_date = '9999-01-01' 
ORDER BY s1.salary DESC,
  s1.emp_no ;
SELECT 
    COUNT(DISTINCT s2.salary) 
  FROM
    salaries s2 
  WHERE  s2.salary >= s1.salary

评论区的解释
仔细区分代码中的s2、s1。比如,一个序列为4,3,2,1。如果要判断这个序列中每个数排在第几名(可以参考成绩排名),那么就看自己的前面有几个人,比如4,>=4的有1人,>=3的有2人,>=2的有3人,>=1的有4人。前面有几个人,count()在代码中表示筛选出几个人,就表示第几名。 distinct应该好理解,比如序列3,2,2,1,>=2的有3,2,2,加上distinct后,就剩下3,2,那么2在序列中排第二名。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值