梳理一遍数据库知识

2-21-4_创建、调整以及删除表格
#1 生成数据表结构
CREATE TABLE users(
	user_id INT PRIMARY KEY,
    name VARCHAR(20),
    age INT,
    city VARCHAR(20),
    state VARCHAR(20),
    monthly_active INT
    #PRIMARY KEY(user_id),
);

# 描述下 表格结构
DESCRIBE users;

#2. 删除一个数据表
DROP TABLE users;

#3 调整一个数据表
ALTER TABLE users ADD gender CHAR(1);

ALTER TABLE users DROP COLUMN gender;
2-21-5_为创建的表格插入数据
#1 像空表中插入数值
INSERT INTO users 
VALUES
(1,'Jack',19,'Dallas','Texas',22),
(2,'Lucy',20,'Boston','Massachusetts',15),
(3,'Tom',13,'Los Angeles','California',8),
(4,'Alice',22,'San Jose','California',17),
(5,'Zhang',32,'Chicago','Illinois',22);

#选择表看一看
SELECT * FROM users;

#2 为Table加上一些限制
CREATE TABLE users2(
	user_id INT,
    name VARCHAR(20) NOT NULL,
    age INT,
    city VARCHAR(20) UNIQUE,
    state VARCHAR(20),
    monthly_active INT,
    PRIMARY KEY(user_id)
);

#插入有空的
INSERT INTO users2 VALUES (1,NULL,19,'Dallas','Texas',22);

INSERT INTO users2 (user_id,age,city,state,monthly_active) 
VALUES (1,19,'Dallas','Texas',22);

#插入不独特的
INSERT INTO users2 VALUES (1,'Tom',19,'Dallas','Texas',22);
INSERT INTO users2 VALUES (2,'Jerry',19,'Dallas','Texas',22);

DROP TABLE users2;

#3 为Table加上缺省值
CREATE TABLE users3(
	user_id INT,
    name VARCHAR(20) NOT NULL,
    age INT,
    city VARCHAR(20) DEFAULT 'unknown',
    state VARCHAR(20),
    monthly_active INT,
    PRIMARY KEY(user_id)
);

INSERT INTO users3 (user_id,name,age,state,monthly_active) 
VALUES (1,'Tom',19,'Texas',22);

# Auto增加主键,可以输入重复的进去了
CREATE TABLE users4(
    user_id INT AUTO_INCREMENT, 
    name VARCHAR(20),
    age INT,
    city VARCHAR(20),
    state VARCHAR(20),
    monthly_active INT,
    PRIMARY KEY(user_id)
);
INSERT INTO users4 (name,age,city,state,monthly_active) VALUES ('Jerry',19,'Dallas','Texas',22);
INSERT INTO users4 (name,age,city,state,monthly_active) VALUES ('Jerry',19,'Dallas','Texas',22);
INSERT INTO users4 (name,age,city,state,monthly_active) VALUES ('Jerry',19,'Dallas','Texas',22);
SELECT * FROM users4;
2-21-6_更新和删除表格里的数据
SELECT * from users;
# Close safe 模式,在Myworkbench那个tab下preference下的SQL Editor,
# 把最后一项check去除,从新连接workbench。

#1 将California设置为CA
UPDATE users
SET state='CA'
WHERE state='California';

#将id=1的名字和年龄修改下
UPDATE users
SET name='Jackie',age=29
WHERE user_id=1;#2 删除符合某种条件的record
DELETE FROM users
WHERE user_id=4;
2-21-7_基本SQL查询语句
# 重新构建users table
DROP TABLE users;
CREATE TABLE users(
	user_id INT PRIMARY KEY,
    name VARCHAR(20),
    age INT,
    city VARCHAR(20),
    state VARCHAR(20),
    monthly_active INT
    #PRIMARY KEY(user_id),
);

INSERT INTO users 
VALUES
(1,'Jack',19,'Dallas','Texas',22),
(2,'Lucy',20,'Boston','Massachusetts',15),
(3,'Tom',13,'Los Angeles','California',8),
(4,'Alice',22,'San Jose','California',17),
(5,'Zhang',32,'Chicago','Illinois',22);

####正式开始####
#1. SELECT Sentence
#全选
SELECT * FROM users;
#选名字变量
SELECT name FROM users;
#选多变量
SELECT name, age,city FROM users; 
#
SELECT users.name, users.age 
FROM users;

#2.Order语句排序
#排序
SELECT users.name, users.age 
FROM users
ORDER BY name;

#多变量排序
SELECT * 
FROM users
ORDER BY state,age;


#3 LIMIT 语句 选择出年龄最大用户记录
SELECT * 
FROM users
ORDER BY age DESC
LIMIT 1;

#4  WHERE 语句,选出年龄在18到22间的人(包括18和22)
SELECT * 
FROM users
WHERE age>=18 AND age<=22;
#或者写 WHERE age BETWEEN 18 AND 22; (包括18和22)

SELECT * 
FROM users
WHERE age>=18 AND age<=22
ORDER BY age;

SQL实战
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#Task 1 获取全部Worker_Info信息
SELECT * 
FROM Worker_Info;

#Task 2 从Worker_Info中获取3到5号员工信息
SELECT * 
FROM Worker_Info
WHERE worker_id in (3,4,5);

#Task 3 获取Worker_Info中表格员工的first_name,并按照最后两个字母进行升序排序(相同的按Worker_id)
SELECT first_name, worker_id 
FROM Worker_Info
ORDER BY first_name, worker_id;
 
#Task 4 查找年龄最小的入职员工信息
SELECT * 
FROM Worker_Info
ORDER BY birthday DESC
LIMIT 1;

#Task 5 查找年龄第三小的员工入职信息
SELECT *
FROM (SELECT *
	  FROM Worker_Info
	  ORDER BY birthday DESC
	  LIMIT 3) AS t
ORDER BY t.birthday 
LIMIT 1;

#Task 6 获取所有非supervisors的员工编号(两种方法)
# 方法一:使用NOT IN
SELECT worker_id 
FROM Worker_Info 
WHERE worker_id NOT IN
	(SELECT DISTINCT sup_id 
		FROM Worker_Info 
		WHERE sup_id IS NOT NULL); 

# 方法二:用LEFT JOIN匹配没有被匹配到的就不是supervisor
#先看看Join后的效果
SELECT t1.worker_id,t2.sup_id
FROM Worker_Info as t1
LEFT JOIN
(SELECT DISTINCT sup_id as sup_id FROM Worker_Info) as t2
ON (t1.worker_id=t2.sup_id);

#正式写
SELECT t1.worker_id
FROM Worker_Info as t1
LEFT JOIN
(SELECT DISTINCT sup_id as sup_id FROM Worker_Info) as t2
ON (t1.worker_id=t2.sup_id)
WHERE t2.sup_id IS NULL;

# Task 7获取所有员工编号为偶数的员工信息
SELECT * FROM Worker_Info
WHERE MOD(worker_id,2)=0;

SELECT * FROM Worker_Info
WHERE worker_id%2=0;

# Task 8找出每个员工的销售额,NULL记为0
# t2表格group每个有销售额的员工销售总和,中间的t3为了处理NULL视作0的问题,然后拿出来在做一层
SELECT t3.worker_id,t3.total/t3.payment as ratio
FROM
(SELECT t1.worker_id, 
(CASE 
	WHEN t2.total IS NULL THEN 0
	ELSE t2.total
	END) as total,t1.payment
FROM Worker_Info as t1 
LEFT JOIN 
(SELECT worker_id, SUM(total_revenue) as total
	FROM Sales_Info
	GROUP BY worker_id) as t2
ON(t1.worker_id=t2.worker_id)) as t3
ORDER BY ratio DESC;

# Task 9找出公司最大客户的名字
#先试试select * 给大家看
SELECT t2.customer_name,t1.total
#2
FROM Customer_Info as t2
INNER JOIN 
#1
(SELECT customer_id, SUM(total_revenue) as total 
FROM Sales_Info
GROUP BY customer_id) as t1

ON (t1.customer_id=t2.customer_id)
#3
ORDER BY t1.total DESC
LIMIT 1;
# date|post_id|action{open, close, report}|user_id|reason 

#建立需要数据

CREATE TABLE view_post(
	id INT AUTO_INCREMENT, 
	date DATE,
	post_id INT,
	action VARCHAR(10),
	user_id INT,
	reason VARCHAR(30) DEFAULT NULL, 
	PRIMARY KEY (id)
);

INSERT INTO view_post (date,post_id,action,user_id,reason)
VALUES ('2010-10-20',1,'open',5,NULL),
('2010-10-20',1,'close',5,NULL),
('2010-10-20',2,'open',3,NULL),
('2010-10-20',2,'report',3,'SPAM'),
('2010-10-20',2,'close',3,NULL),
('2010-10-20',2,'open',5,NULL),
('2010-10-20',2,'report',5,'Advertising'),
('2010-10-20',2,'close',5,NULL),
('2010-10-20',3,'open',4,NULL),
('2010-10-20',3,'report',4,'SPAM'),
('2010-10-20',3,'close',4,NULL),
('2010-10-20',4,'open',5,NULL),
('2010-10-20',4,'report',5,'SPAM'),
('2010-10-20',4,'close',5,NULL),
('2010-10-20',4,'open',6,NULL),
('2010-10-20',4,'report',6,'SPAM'),
('2010-10-20',5,'open',3,NULL),
('2010-10-20',5,'report',3,'Inappropriate Content'),
('2010-10-19',5,'open',1,NULL),
('2010-10-19',5,'report',1,'Inappropriate Content'),
('2010-10-19',2,'report',5,'Advertising'),
('2010-10-19',2,'close',5,NULL),
('2010-10-19',3,'open',4,NULL),
('2010-10-19',3,'report',4,'SPAM'),
('2010-10-19',3,'close',4,NULL);

#越讲越简单,不断带大家看表的中间结果

# 方法一
SELECT * from view_post
WHERE reason is not NULL AND date='2010-10-20';

#多变量group其实就是去重操作
SELECT t1.post_id,t1.reason FROM
(SELECT * from view_post
WHERE reason is not NULL AND date='2010-10-20') as t1
GROUP BY t1.post_id,t1.reason;


SELECT t2.reason,count(t2.reason) FROM
(SELECT t1.post_id,t1.reason FROM
(SELECT * from view_post
WHERE reason is not NULL AND date='2010-10-20') as t1
GROUP BY t1.post_id,t1.reason) as t2
GROUP BY t2.reason;

#方法二
SELECT DISTINCT date,post_id,action,reason
FROM view_post;

SELECT DISTINCT date,post_id,action,reason
FROM view_post;
WHERE action='report' AND date='2010-10-20';


SELECT t.reason,COUNT(t.reason) FROM
(SELECT DISTINCT date,post_id,action,reason
FROM view_post
WHERE reason IS NOT NULL AND date='2010-10-20') as t
GROUP BY t.reason;

#方法三
#先带大家看一下表的临时结果
SELECT *
FROM view_post
WHERE date='2010-10-20'
AND action='report';

#再group by reason,看每个reason下 "不同" 的post_id
SELECT reason, COUNT(DISTINCT post_id)
FROM view_post
WHERE date='2010-10-20'
AND action='report'
GROUP BY reason;

# 表一 adv_info:advertiser_id | ad_id | spend
# 表二 ad_id | payment

#建立需要数据,为了方便就不涉及主键外键
CREATE TABLE adv_info(
	advertiser_id INT,
	ad_id INT,
	spend INT
);


CREATE TABLE ad_info(
	ad_id INT,
	payment INT
);

INSERT INTO adv_info
VALUES 
(1,1,10000),
(1,2,5000),
(2,3,20000),
(3,4,30000),
(3,5,1000),
(4,6,100),
(5,7,0);

INSERT INTO ad_info
VALUES 
(1,10000),
(2,12000),
(1,10000),
(3,60000),
(4,20000),
(5,3000),
(5,200),
(4,2000),
(6,0),
(7,0);

#1. 求广告上花费最高的雇主
SELECT advertiser_id, SUM(spend) as total_spend
FROM adv_info
GROUP BY total_spend
LIMIT 1;

#2. 求至少一次conversion的advertiser占总体百分比

#这里面从新命名是为了避免到后面临时表格中出现两个ad_id而无法select *

#查找每个广告的总收入
SELECT ad_id as ad_id2,SUM(payment) as total_payment 
FROM ad_info 
GROUP BY ad_id2 

#将广告收入和广告主去匹配
SELECT *
	FROM adv_info as t2
	LEFT JOIN
		(SELECT ad_id as ad_id2,SUM(payment) as total_payment 
			FROM ad_info 
			GROUP BY ad_id2) as t1
		ON(t1.ad_id2=t2.ad_id)

#统计每个广告主收入
SELECT t3.advertiser_id, sum(t3.total_payment) as total_payment
	FROM
	(SELECT *
	FROM adv_info as t2
	LEFT JOIN
		(SELECT ad_id as ad_id2,SUM(payment) as total_payment 
			FROM ad_info 
			GROUP BY ad_id2) as t1
		ON(t1.ad_id2=t2.ad_id)) as t3
	GROUP BY t3.advertiser_id

#计算那些有收入的/全部广告主
SELECT SUM(CASE WHEN t4.total_payment!=0 THEN 1 ELSE 0 END)/COUNT(advertiser_id) as ratio
FROM
(SELECT t3.advertiser_id, sum(t3.total_payment) as total_payment
	FROM
	(SELECT *
	FROM adv_info as t2
	LEFT JOIN
		(SELECT ad_id as ad_id2,SUM(payment) as total_payment 
			FROM ad_info 
			GROUP BY ad_id2) as t1
		ON(t1.ad_id2=t2.ad_id)) as t3
	GROUP BY t3.advertiser_id) as t4;


#3  求每个广告主(advertiser)的ROI(回报率,就是payment/spend)
#根据上一题,我们看看t3是什么表
SELECT *
FROM adv_info as t2
LEFT JOIN
(SELECT ad_id as ad_id2,SUM(payment) as total_payment 
 FROM ad_info 
 GROUP BY ad_id2) as t1
	ON(t1.ad_id2=t2.ad_id);


# 直接按advertiser_id进行group,每个广告主用总收入/总费用
SELECT t3.advertiser_id, SUM(t3.total_payment)/SUM(t3.spend) as ROI
FROM
(SELECT *
FROM adv_info as t2
LEFT JOIN
(SELECT ad_id as ad_id2,SUM(payment) as total_payment 
 FROM ad_info 
 GROUP BY ad_id2) as t1
	ON(t1.ad_id2=t2.ad_id)) as t3
GROUP BY t3.advertiser_id;


#仅仅是为了将除以0以后是NULL的雇主变成文字‘unsure’.
SELECT t4.advertiser_id, (CASE WHEN t4.ROI is NULL THEN 'unsure' ELSE t4.ROI END) as ROI
FROM
(SELECT t3.advertiser_id, SUM(t3.total_payment)/SUM(t3.spend) as ROI
FROM
(SELECT *
FROM adv_info as t2
LEFT JOIN
(SELECT ad_id as ad_id2,SUM(payment) as total_payment 
 FROM ad_info 
 GROUP BY ad_id2) as t1
	ON(t1.ad_id2=t2.ad_id)) as t3
GROUP BY t3.advertiser_id) as t4;

牛客网习题汇总:


1.查找入职员工时间排名倒数第三的员工所有信息
select * from employees order by hire_date desc limit 2,1;
数据如下:
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));

查找各个部门当前(to_date='9999-01-01')领导当前薪水详情以及其对应部门编号dept_no

select salaries.emp_no,salaries.salary,salaries.from_date,salaries.to_date,dept_manager.dept_no
from salaries inner join dept_manager
on dept_manager.emp_no = salaries.emp_no
and dept_manager.to_date = '9999-01-01'
and salaries.to_date = '9999-01-01';

select s.* ,d.dept_no
from salaries as s 
join dept_manager as d 
on s.emp_no=d.emp_no
where s.to_date = '9999-01-01'
    and    d.to_date='9999-01-01';

CREATE TABLE `dept_manager` (
`dept_no` char(4) NOT NULL,
`emp_no` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));
发布了49 篇原创文章 · 获赞 9 · 访问量 3456

猜你喜欢

转载自blog.csdn.net/qq_39817865/article/details/103257355