1 安装MySQL
进入MySQL官网,登录
我之后改了个,怕忘记 先把原始的放上去,哈哈
安装好之后,启动的时候发现总是启动不了,原因是端口被占用了,所以导致无法启动MySQL
查看端口占用命令 sudo losf -i : 3306
冒号后是你的端口号
MySQL常用端口就是3306,发现被占用了 ,应该是上一个没有卸载干净的MySQL
用命令 sudo kill -9 8593 (8593是占用端口的PID值)
把端口程序杀死之后 发现能顺利启动了。
启动后
2 MySQL卸载
执行下列命令
sudo rm /usr/local/mysql
sudo rm -rf /usr/local/mysql*
sudo rm -rf /Library/StartupItems/MySQLCOM
sudo rm -rf /Library/PreferencePanes/My*
rm -rf ~/Library/PreferencePanes/My*
sudo rm -rf /Library/Receipts/mysql*
sudo rm -rf /Library/Receipts/MySQL*
sudo rm -rf /var/db/receipts/com.mysql.*
其实不同的安装方式有些东西的存储位置不一样,删除完检查一下下面这些文件是否删除了,没有的话则删除掉:
/usr/local/Cellar 里的mysql文件
/usr/local/var 里的mysql文件
/cd tmp 里的mysql.sock, mysql.sock.lock, my.cnf文件
pid文件和err文件都在/usr/local/var/mysql里确保删除了
brew安装的安装包存储在/usr/local/Library/Cache/Homebrew也可以一并删除
执行brew cleanup
执行完基本就卸载干净了,可以从新安装了
最后终于进来了,快哭了
3 导入数据库
下载数据包到桌面
然后启动本地MySQL
mysql -u root -p
输入自己设置的密码(123)
就启动了
然后倒入数据库,先要创建数据库
mysql>CREATE DATABASE IF NOT EXISTS yibaidb DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
mysql> use yiibaidb;
然后是导入数据库
mysql> use yiibaidb;
mysql> source /Users/qiaoye/Desktop/yiibaidb.sql;
然后他就自己在哪里导入了,等到结束后我们来测试下我们导入的数据库;
mysql> select city,phone,country from `offices`;
4 学习查询语句
使用select语句从表中或者视图中获取数据,表由行和列组成,如电子表格。通常,我们只希望看到子集行,子集列,或者两者的组合。select是结果集,它是由行列表,每行由相同的数目组成。
yibaidb中的employees表的结构。它是8列:员工人数,姓氏,名字,分机,电子邮件,办公室代码,报告,职位。
select语句控制要查那些行和列,例如,如果只对员工的名字和姓氏感兴趣,或者只想查看某位员工信息,select都可以帮助执行操作。
SELECT语句有以下语法:
SELECT之后是逗号分隔列或星号(*)的列表,表示要返回所有列。
FROM指定要查询数据的表或者视图;
JOIN根据某些连接条件从其他表中获取数据;
WHERE过滤结果集中的行;
GROUP BY 将一组行组成小分组,并对每个小分组应用聚合函数。
HAVING过滤器基于GROUP BY子句定义的小分组;
ORDER BY指定用于排序的列的列表;
LIMIT限制返回行的数量;
语句中的SELECT 和 FROM 语句是必须的,其他部分都是可选的;
SELECT 语句允许通过在SELECT子句中指定逗号分隔列的列表来查询表的部分数据。例如,仅要查看员工的名字,姓氏和职位,使用以下查询:
SELECT
lastname,firstname,jobtitle;
FROM
employees;
即使员工表中有很多列,SELECT也只会返回表中的所有行的三列数据
比较下列返回的区别:
SELECT * FROM employees;
如果要获取employees中所有行的数据,可以列出SELECT子句中的所有列名,或者只需使用(*)表示您想从表的所有列获取数据,如下查询:
他返回了employee的所有列和行。应该使用(*)进行测试。建议显示获取数据的列,原因如下:
1 使用星号(*)可能会返回不使用的列的数据。它在MySQL数据库服务器和应用程序之间产生不必要的I/O磁盘和网络流量。
2 如果明确指定列,则结果集更可预测并且更易于管理。想象一下,当您使用星号(*)并且有人通过添加更多列更改表格数据时,将会得到一个与预期结果不同的结果集;
3 使用星号(*)可能会将敏感信息暴露给未经授权的用户;
去重语法
去重语法:SELECT DISTINCT [COLUMN_NAME] FROM [TABLE_NAME]
来看看去重后结果:
注意:
(1)DISTINCT 等关键字建议使用大写,其他的表名建议用小写,便于区分;
(2)DISTINCT关键字要在去重列名之前;
查询前N条语句
mysql查询前10条语句:SELECT * FROM table_name limit 0,10;
case .... end
case函数有两种格式,
简单case函数:
CASE sex
WHEN '1' THEN '男'
WHEN ‘2’ THEN ‘女’
ELSE '其他' END
case 搜索函数:
CASE WHEN sex = '1' THEN '男'
WHEN sex = '2' THEN '女'
ELSE '其他' END
这两种方式,可以实现相同的功能。简单Case函数的写法相对比较简洁,但是和Case搜索函数相比,功能方面会有些限制,比如写判断式。
还有一个需要注意的问题,Case函数只返回第一个符合条件的值,剩下的Case部分将会被自动忽略。
筛选语句 where
如果使用SELECT语句,但不使用WHERE子句在表中查询,则会获取表中的所有数据,这些记录大部分是不想要的记录。
WHERE语句允许根据指定的过滤表达式或条件来指定要选择的行。
假设只想从employees中获取销售代表员工,可以使用以下查询:
SELECT
lastname,firstname,jobtitle
FROM
employees
WHERE
jobtitle = 'Sales Rep'
执行后得到以下结果
即使WHERE子句出现在语句的句尾,但MySQL会首先使用WHERE子句的表达式来选择匹配的行,他选择具有职位名称为销售代表的记录。
例如,要在办公室代码(officeCode)等于1中查找所有销售代表,请使用以下查询:
SELECT lastname,firstname,jobtitle FROM employees WHERE jobtitle='Sales Rep' AND officeCode='1';
WHERE操作符
= 几乎任何数据类型都可以用它
<> 或 != 不等于
< 小于,通常使用数字和日期/时间数据类型
> 大于
<= 小于或等于
>= 大于或等于
以下查询使用不等于(!=)运算符来获取不是销售代表的其它所有员工:
SELECT lastname,firstname,jobtitle FROM employees WHERE jobtitle <> 'Sales Rep';
以下查询将获得办公室代码大于5的每位员工:
办公室代码小于或等于4(<= 4)的员工呢?
通配符是进行模糊查询的时候用到的
% : LIKE '****%' (***指的是已知的模糊的文本)
_: LIKE '***_' (***指的是已知的模糊的文本)
用通配符_时,为单字符匹配,要注意空格:
5. 分组语句 GROUP BY
作用:GROUP BY 语句根据一个或多个列对结果集进行分组。会把值相同放到一个组中,最终查询出的结果只会显示组中一条记录。
1)基本用法:
根据 sex 字段分组,查询用户名、年龄、电话、性别。
这就分组成功了!男的一组 女的一组,还有一组那啥,咳咳,搞不清楚的,但是都只显示了组中一条记录,我们的效果不够明显,接着看下面的例子。)
2)GROUP BY 语句中的GROUP_CONCAT()函数
根据sex 字段进行分组并查看username字段和age字段的详细信息。(这下对基本用法就很好理解了。因为他默认只显示了组中一条记录,如果想看组内所以的用户信息,就需要用到GROUP_CONCAT()函数。接着往下↓)
SELECT GROUP_CONCAT(username),GROUP_CONCAT(age),sex FROM testusers GROUPBY sex;
3)COUNT()函数:统计记录总数
根据sex 字段分组,查询性别和用户名,年龄的详细信息并统计各组用户数量。
(查出来记录以后自己数?太萌了吧?利用COUNT()函数统计记录总数。当然细心的兄dei已经发现问题了,为什么只有三个男的,COUNT()函数统计出来四个?[难道有两根?!] ,咳咳,是因为在COUNT()函数中,写COUNT(*)会统计我们表中的NULL值,如果不想统计NULL值,请写COUNT(字段名)。看我们上面的表中,最后一条记录的username是NULL,所以只有三个男的却统计出四根diao.呸,统计出四个男生。PS:代码段中AS xxx=取别名)
SELECT COUNT(*) AS totalUsers, GROUP_CONCAT(username) AS userDetail ,GROUP_CONCAT(age) AS userAge,sex FROM testusers GROUP BY sex;
4)加WHERE条件
在年龄大于等于18的范围内,根据sex分组,查询性别和用户名、年龄的详细信息并统计各组用户数量
5)聚合函数[‘SUM()求和函数’,’MAX()函数:求最大值’,’MIN()函数:求最小值’,’AVG()函数:求平均值’]。一个例子整合运用(计算每组用户薪水的各项值)。
SELECT COUNT(*) AS totalUsers,GROUP_CONCAT(username) AS userDetail,sex, SUM(salary) AS sum_salary,MAX(salary) AS max_salary,MAX(salary) AS max_salary,MIN(salary) AS min_salary,AVG(salary) AS avg_salary FROM testusers GROUP BY sex;
6):HAVING 子句:对分组结果进行二次筛选
根据性别分组,查询性别和用户名,年龄的详细信息并统计各组用户总数,得出结果后进行二次筛选出用户总数在5人及以上的组。相当于WHERE是一次筛选,HAVING是在二/再次筛选.
SELECT COUNT(*) AS totalUsers,GROUP_CONCAT(age) AS userAge,GROUP_CONCAT(username) AS userDetail,sex FROM testusers GROUP BY sex HAVING totalUsers>=5;
6. 排序语句 ORDER BY
SELECT field1, field2,...fieldN table_name1, table_name2...ORDER BY field1, [field2...] [ASC [DESC]]
ASC 是升序
DESC 是降序
7. 函数 时间函数 数值函数 字符串函数
列举了详细的函数说明
8. SQL注释
1 单行注释可以用“#”
2 多行注释可以用/**/
项目一:查找重复的电子邮箱
CREATE TABLE email (ID INT NOT NULL PRIMARY KEY, Email VARCHAR(255)); %创建表格
INSERT INTO email VALUES('1','a@b.com'); %输入表格内容
INSERT INTO email VALUES('2','c@d.com');
INSERT INTO email VALUES('3','a@b.com');
SELECT Email %查找步骤
FROM email
GROUP BY email having count (Email)>1;
项目二:查找大国
CREATE TABLE World( %创建表格
country VARCHAR(50) NOT NULL,
continent VARCHAR(50) NOT NULL,
area INT NOT NULL,
population INT NOT NULL,
gdp INT NOT NULL
);
INSERT INTO World %输入表格内容
VALUES('Afghanistan','Asia',652230,25500100,20343000);
INSERT INTO World
VALUES('Albania','Europe',28748,2831741,12960000);
INSERT INTO World
VALUES('Algeria','Africa',2381741,37100000,188681000);
INSERT INTO World
VALUES('Andorra','Europe',468,78115,3712000);
INSERT INTO World
VALUES('Angola','Africa',1246700,20609294,100990000);
SELECT country,populaiton,area %查找步骤
FROM World
WHERE area>3000000 or population>25000000;
MySQL表操作
1 MySQL表数据类型
MySQL支出多种类型,大致分为三类,数值,日期/时间 和 字符串类型
数值类型
MySQL支持所有标准SQL数值数据类型。
这些数值包括严格数值数据类型(INTGER、SMALLINT、DECIMAL和NUMERIC)以及近似数值类型(FLOAT、REAL、DOUBLE、PRECISION)
日期和时间
表示时间值的日期和时间类型为DATATIME DATA TIMESTAMP TIME和YEAR
表示时间类型有一个有效范围和一个零值,当指定不合法的MySQL不能表示的值时使用‘零’值。
字符串类型
字符串类型是指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和 SET,该节描述了这些类型如何工作以及在如何在查询中使用这些类型
MySQL主键
表中每一行都应该有可以唯一标识自己的一列(或一组列)。
一个顾客可以使用顾客编号列,而订单可以使用订单ID
主键(primary Key)一列(或一组列)其值可以能够唯一区分表中的每一行。
唯一标识表中每行的这个列(或这个组列)称为主键,没有主键,更行或者删除表中的特定行将变得较为困难,因为没有安全的方法保证只涉及相关的行。
虽然并不是总是需要主键,但是大多是数据库设计人员都应该保证他们创建的每个表有一个主键,以便于数据的操作和管理。
表中的任何列都可以作为主键,只要满足以下两个条件:
1 任何两行都不具有相同的主键值
2 每行都必须有一个主键值
主键的最好习惯:
除了强制要求的,还应该保持几个好习惯为:
1 不更新主键列的值
2 不重用主键列的值
3 不在主键中使用可能会更改的值
总之不应该使用一个具有实际意义的id作为主键,并且一个表必须有一个主键,为方便扩展,松耦合,高可用的系统做铺垫。
MySQL创建数据表
创建MySQL数据表需要以下信息
1 表名
2 表字段名
3 定义每个表字段
以下为创建数据表的SQL通用语法:
CREAT TABLE table_name (column_name column_type);
以下例子
CREATE TABLE IF NOT EXISTS `courses`(`student_id` INT UNSIGNED AUTO_INCREMENT,`student` VARCHAR(100) NOT NULL,`class` VARCHAR(100) NOT NULL,PRIMARY KEY(student_id));
创建表之前要先依赖数据库 才可以建表;
1 如果你不想字段为 NULL 可以设置字段的属性为 NOT NULL, 在操作数据库时如果输入该字段的数据为NULL ,就会报错。
2 AUTO_INCREMENT定义列为自增的属性,一般用于主键,数值会自动加1。
3 PRIMARY KEY关键字用于定义列为主键。 您可以使用多列来定义主键,列间以逗号分隔。
4 ENGINE 设置存储引擎,CHARSET 设置编码。
存储引擎有3重:InnoDB MyISAM MEMORY
InnoDB:支持事务处理,支持外键,支持崩溃修复能力和并发控制。如果需要对事务的完整性要求比较高(比如银行),要求实现并发控制(比如售票),那选择InnoDB有很大的优势。如果需要频繁的更新、删除操作的数据库,也可以选择InnoDB,因为支持事务的提交(commit)和回滚(rollback)。
MyISAM:插入数据快,空间和内存使用比较低。如果表主要是用于插入新记录和读出记录,那么选择MyISAM能实现处理高效率。如果应用的完整性、并发性要求比 较低,也可以使用。
MEMORY:所有的数据都在内存中,数据的处理速度快,但是安全性不高。如果需要很快的读写速度,对数据的安全性要求较低,可以选择MEMOEY。它对表的大小有要求,不能建立太大的表。所以,这类数据库只使用在相对较小的数据库表。
用SQL向表中添加数据:
MySQL表中使用INSERT INTO SQL 来添加数据:
INSERT INTO table_name (field1,field2....fieldN)
VALUES(value1,value2....valueN);
如果数据是字符型的,必须使用单引号或者双引号如 "value"
一次性插入多个
// 一次性插入多个
$ insert into tab_name (col_1, col_2) values
('value_1a', 'value_1b'),
('value_2a', 'value_2b');
//插入时有主键冲突,改为更新操作
insert into tab_name (id, col_1, col_2) values
(13, 'value_1', 'value_2')
on duplicate key update
col_1 = 'value_1', col_2 = 'value_2'
// 将查询结果插入到数据(不应该出现在真实项目里,因为基数大时,会增加大量数据)
$ insert into tab_name (col_1, col_2) select col_1, col_2 from tab_name2
// 字段数和格式相同,才能讲不通字段名的插入
insert into tab_name (col_1, col_2) select col_3, col_4 from tab_name3
// 冲突替换,否则插入
replace into teacher values
(1, 'value_1', 'value_2', 'value_3')
// 导入数据(使用outfile导出的数据,避免导入时主键冲突,应为null)
// 也支持数据格式设置,同outfile
$ load data infile 'path' into tab_name;
插入数据
mysql> INSERT INTO courses(student,class) value ("A","math");
这是插入一行数据之后的表格;
插入完毕,现在寻找大于5节的课程。
mysql> select class from courses group by class having count(*)>=5;
首先选择了class,并按照这列进行分组,把组别大于5选择出来,里边有2次选择,having count。
4 用SQL语句删除表
MySQL中删除数据表是非常容易操作的, 但是你再进行删除表操作时要非常小心,因为执行删除命令后所有数据都会消失。
DROP TABLE table_name ;
删除表内数据用 delete 格式为:
delete from 表名 where 删除条件;
实例:删除学生表内姓名为张三的记录。
delete from student where T_name = "张三";
清除表内数据,但是保留表结构用truncate。格式为:
truncate table "表名";
实例:清除学生表内的所有数据。
truncate table "student";
1 当你不在需要该表的时候,用drop;
2 当你仍要保留该表,但是要删除所以记录的时候,用truncate;
3 当你要删除部分记录的时候,用delete;
5 用SQL语句修改表
当我们需要修改数据表名或者修改数据表字段时,就需要使用到MySQL ALTER命令。
删除,添加或修改表字段
如下命令使用了 ALTER 命令及 DROP 子句来删除以上创建表的 i 字段:
mysql> ALTER TABLE testalter_tbl DROP i;
如果数据表中只剩余一个字段则无法使用DROP来删除字段。
MySQL 中使用 ADD 子句来向数据表中添加列,如下实例在表 testalter_tbl 中添加 i 字段,并定义数据类型:
mysql> ALTER TABLE testalter_tbl ADD i INT;
执行以上命令后,i 字段会自动添加到数据表字段的末尾。
如果你需要指定新增字段的位置,可以使用MySQL提供的关键字FIRST(设定为第一列)AFTER字段名(设定位于某个字段之后)。
ALTER TABLE testalter_tbl DROP i;
ALTER TABLE testalter_tbl ADD i INT FIRST;
ALTER TABLE testalter_tbl DROP i;
ALTER TABLE testalter_tbl ADD i INT AFTER c;
修改字段类型及名称
如果需要修改字段类型及名称, 你可以在ALTER命令中使用 MODIFY 或 CHANGE 子句 。
例如,把字段 c 的类型从 CHAR(1) 改为 CHAR(10),可以执行以下命令:
ALTER TABLE testalter_tbl MODIFY c CHAR(10);
使用 CHANGE 子句, 语法有很大的不同。 在 CHANGE 关键字之后,紧跟着的是你要修改的字段名,然后指定新字段名及类型。尝试如下实例:
ALTER TABLE testalter_tbl CHANGE i j BIGINT;
ALTER TABLE testalter_tbl CAHNGE j j INT;
ALTER TABLE 对 Null 值和默认值的影响
当你修改字段的时候,你可以指定是否包含值或者是否设置为默认值。
以下实例,指定字段j为NOT NULL 且默认值为 100;
ALTER TABLE testalter_tbl MODIFY j BIGINT NOT NULL DEFAULT 100;
如果不设置默认值,MySQL会自动设置该字段为NULL
修改表名
尝试以下实例将数据表 testalter_tbl 重命名为 alter_tbl:
ALTER TABLE testalter_tbl RENAME TO alter_tbl;
添加列:
ALTER TABLE 表名 ADD COLUMN 列名 VARCHAR(30);
删除列:
ALTER TABLE 表名 DROP COLUMN 列名;
项目四 :交换工资
创建一个salary表
mysql> CREATE TABLE IF NOT EXISTS `salary`(`id` INT UNSIGNED AUTO_INCREMENT,`name` VARCHAR(100) NOT NULL,`sex` VARCHAR(100) NOT NULL,`salary` VARCHAR(100) NOT NULL,PRIMARY KEY(id));
mysql> INSERT INTO salary (name,sex,salary) value ("A","m","2500");
........
交换f 和 m 的值
UPDATE salary SET sex=CASE sex
-> WHEN "f" THEN "m"
-> WHEN "m" THEN "f"
-> END
-> WHERE sex IN("f","m");
使用批量更新的办法就可以了。
输出如下:
2.2 MySQL 基础 (三)- 表联结
MySQL 别名
查询数据是的时候,如果表名很长,使用起来不方便,此时就可以取一个别名,用这个别名代替表的名称。
SELECT * FROM 表名 [AS] 别名;
为表取别名的时候,as关键字可以省略不写
为student 表取别名S,并查询student表中gender字段值为nv记录
为字段取别名
在查询数据的时候,为了显示查询结果更加直观,可以为一个字段取一个别名,
SELECT 字段名 [AS] 别名 FROM 表名;
查询student表中所有记录的,name和gender字段值,并为这两个字段起别名,stu_name和stu_gender
可以看到,显示的查询结果是指定的别名,而不是student表中的字段名。
INNER JOIN
在真正的应用中经常需要从多个数据表中读取数据。本节介绍如何使用MySQL的JOIN在两个或多个表中查询数据。
你可以在SELECT UPDATE DELETE语句中使用MySQL的JOIN来联合多表来查询。
INNER JOIN (内连接 或 等值连接):获得两个表中字段匹配关系的记录。
LEFT JOIN (左连接):获取左表所有记录,即使右表没有对应匹配的记录。
RIGHT JOIN(右连接):与LEFT JOIN相反,用于获取右表的所有记录,即使左表没有对应的匹配的连接。
CROSS JOIN(交叉连接):
为了方便理解每种类型的连接,我们是使用以下具有以下结构的表:t1 和 t2表:
USE testdb;
CREATE TABLEt1 (id INT PRIMARYKEY, pattern VARCHAR(50) NOTNULL);
CREATE TABLEt2 (id VARCHAR(50) PRIMARYKEY, pattern VARCHAR(50) NOTNULL);
t1 和 t2 表都有pattern列,此列也是两个表的公共列。执行以下插入语句将数据插入到t1 和 t2 中
INSERT INTO t1(id,pattern)
VALUES
(1,'Divot'),(2,'Brick'),(3,'Grid');
INSERT INTO t2 (id,pattern)
VALUES
('A','Brick'),('B','Grid'),('C','Diamond');
MySQL交叉连接 CROSS JOIN
CROSS JOIN 生成来自多个表的行的笛卡尔乘积。假设你使用CROSS JOIN 来连接t1 和 t2表,结果集将包括t1 表中的行和 t2 表中的行的组合。
要执行交叉连接(最后得到笛卡尔乘积),请使用CROSS JOIN子句,如以下语句所示;
SELECT t1.id, t2.id FROM t1 CROSS JOIN t2;
执行以下语句可以得到以下结果:
t1 表中的每一行与t2 表中的每一行结合形成笛卡尔乘积。
下图显示了t1 和 t2 表之间的CROSS JOIN 连接;
MySQL的内连接 INNER JOIN
要形成一个INNER JOIN连接子句,需要一个称之为连接谓词的条件。INNER JOIN需要两个连接的表中的行具有匹配的列值。INNER JOIN通过组合基于连接谓词的两个连接表的列值来创建结果集。
要连接两个表。INNER JOIN 将第一个表中的每一行与第二表中的每一行进行比较,以找到满足连接谓词的行对。每当通过匹配非NULL值来满足连接谓词的时,两个表中每个匹配的列值将包含在结果集中(可以简单理解为两个表的交集)。
SELECT t1.id t2.id
FROM
t1
INNER JOIN
t2 ON t1.pattern = t2.pattern;
在上面语句中,以下表达式是连接谓词:
t1.pattern = t2.pattern
这意味着t1 和 t2表中的行必须在 pattern列中具有相同的值才能包含在结果中。
下图显示了t1 和 t2 表之间的 INNER JOIN
在此图中,两个表中的行必须具有相同pattern列值,才能包含在结果集中。
MySQL左连接(LEFT JOIN)
类似于INNER JOIN,LEFT JOIN也需要连接谓词。当使用连接LEFT JOIN连接两个表中的时,介绍了左表和右表的概念。
与INNER JOIN 不同 LEFT JOIN 返回左表的所有行,包括连接谓词的所有行。对于不匹配连接谓词的行,右表的列将使用NULL值显示在结果集中。
以下子句使用 LEFT JOIN 连接t1 和 t2 表:
SELECT t1.id, t2.id
FROM
t1
LEFT JOIN
t2 ON t1.pattern = t2.pattern
ORDER BY t1.id;
如上所见,t1表中的所有行都包含在结果集中。对于t2 表(右表)中没有任何匹配t1 表(左表)中的行,在t2表中的列使用NULL显示。
MySQL右连接(RIGHT JOIN)
右连接(RIGHT JOIN)类似于左连接(LEFT JOIN)除了表的处理是相反的。使用RIGHT JOIN,右表t2 中的每一行将显示在结果集中。对于右表没有左表(t1)中的匹配的行,左表t1 会显示NULL
SELECT
t1.id ,t2.id
FROM
t1
RIGHT JOIN
t2 ON t1.pattern = t2.pattern
ORDER BY t2.id
UNION
MySQL UNION 操作符用于连接两个以上的 SELECT 语句的结果组合到一个结果集合中。多个 SELECT 语句会删除重复的数据。
SELECT expression1, expression2, ... expression_n
FROM tables
[WHERE conditions]
UNION [ALL | DISTINCT]
SELECT expression1, expression2, ... expression_n
FROM tables
[WHERE conditions];
1 expression1, expression2, ... expression_n: 要检索的列。
2 tables: 要检索的数据表。
3 WHERE conditions: 可选, 检索条件。
4 DISTINCT: 可选,删除结果集中重复的数据。默认情况下 UNION 操作符已经删除了重复数据,所以 DISTINCT 修饰符对结果没啥影响。
5 ALL: 可选,返回所有结果集,包含重复数据。
SQL UNION 实例
下面的 SQL 语句从 "Websites" 和 "apps" 表中选取所有不同的country(只有不同的值):
SELECT country FROM Websites
UNION
SELECT country FROM apps
ORDER BY country;
UNION 不能用于列出两个表中所有的country。如果一个网站和app来自同一个国家,每个国家只会出现一次,UNION只会选取不同的值,请使用UNION ALL 来选取不重复的值!
SELECT country FROM Websites
UNION ALL
SELECT country FROM apps
ORDER BY country;
带有 WHERE 的 SQL UNION ALL
下面的 SQL 语句使用 UNION ALL 从 "Websites" 和 "apps" 表中选取所有的中国(CN)的数据(也有重复的值):
SELECT country,name FROM Websites
WHERE conutry='CN'
UNION ALL
SELECT country,app_name FROM apps
WHERE conutry='CN'
ORDER BY country;
3作业:
mysql>select*from person;
mysql>select*from address;
mysql>select FirstName, LastName, City, State from Address
left join Person
on Person.PersonId=Address.PersonId order by Person.PersonId;
mysql>create table emailtmp as select*fromemail;
mysql>delete emailtmp from emailtmp,email
where emailtmp.email=email.email and emailtmp.id>email.id;
mysql>select*from email;
mysql>select*from emailtmp;
MySQL文件的导入以及导出
通过MySQL客户端shell连接到服务器,选择使用的数据库,输入SQL代码。
作业
项目七: 各部门工资最高的员工(难度:中等)
创建Employee 表,包含所有员工信息,每个员工有其对应的 Id, salary 和 department Id。
+----+-------+--------+--------------+
| Id | Name | Salary | Department
| 1 | Joe | 70000 | 1 |
| 2 | Henry | 80000 | 2 |
| 3 | Sam | 60000 | 2 |
| 4 | Max | 90000 | 1 |
+----+-------+--------+--------------+
创建Department 表,包含公司所有部门的信息。
+----+----------+
| Id | Name |
| 1 | IT |
| 2 | Sales |
+----+----------+
编写一个 SQL 查询,找出每个部门工资最高的员工。例如,根据上述给定的表格,Max 在 IT 部门有最高工资,Henry 在 Sales 部门有最高工资。
+------------+----------+--------+
| Department | Employee | Salary |
| IT | Max | 90000 |
| Sales | Henry | 80000 |
+------------+----------+--------+
CREATE TABLE IF NOT EXISTS `Employee`(`id` INT UNSIGEND AUTO_INCREMENT, `NAME` VARCHAR(100) NOT NULL, `Salary` VARCHAR(100) NOT NULL, `Department` INT NOT NULL, PRIMARY KEY(`id`));
mysql> INSERT INTO Employee(id,NAME,Salary,Department) VALUES(1,"Joe","70000",1);
mysql> INSERT INTO Employee(id,NAME,Salary,Department) VALUES(2,"Henry","80000",2);
...
mysql> INSERT INTO Employee(id,NAME,Salary,Department) VALUES(4,"Max","90000",1);
mysql> CREATE TABLE `Department`(id INT PRIMARY KEY,Name VARCHAR(100));
mysql> insert into Department(id,Name) values (1,"IT");
mysql> insert into Department(id,Name) values (2,"Sales");
mysql> select Department.name as Department,Employee.name as Employee,Salary from Department,Employee where Employee.Department = Department.id AND Employee.Salary IN(select Max(salary) from Employee group by Department);
项目八: 换座位(难度:中等)
小美是一所中学的信息科技老师,她有一张 seat 座位表,平时用来储存学生名字和与他们相对应的座位 id。
其中纵列的 **id **是连续递增的
小美想改变相邻俩学生的座位。
你能不能帮她写一个 SQL query 来输出小美想要的结果呢?
请创建如下所示seat表:
+---------+---------+
| id | student |
| 1 | Abbot |
| 2 | Doris |
| 3 | Emerson |
| 4 | Green |
| 5 | Jeames |
+---------+---------+
假如数据输入的是上表,则输出结果如下:
+---------+---------+
| id | student |
| 1 | Doris |
| 2 | Abbot |
| 3 | Green |
| 4 | Emerson |
| 5 | Jeames |
+---------+---------+
如果学生人数是奇数,则不需要改变最后一个同学的座位。
mysql> select(case when mod(id,2)=1 and id=(select count(*) from seat) then id when mod(id,2)=1 then id+1 else id-1 end) as ID,Student from seat order by id;
count(*)返回总行数
mod(id,2)= 1 返回奇书
项目九: 分数排名(难度:中等)
编写一个 SQL 查询来实现分数排名。如果两个分数相同,则两个分数排名(Rank)相同。请注意,平分后的下一个名次应该是下一个连续的整数值。换句话说,名次之间不应该有“间隔”。
创建以下score表:
+----+-------+
| Id | Score |
| 1 | 3.50 |
| 2 | 3.65 |
| 3 | 4.00 |
| 4 | 3.85 |
| 5 | 4.00 |
| 6 | 3.65 |
+----+-------+
例如,根据上述给定的 Scores 表,你的查询应该返回(按分数从高到低排列):
+-------+------+
| Score | Rank |
| 4.00 | 1 |
| 4.00 | 1 |
| 3.85 | 2 |
| 3.65 | 3 |
| 3.65 | 3 |
| 3.50 | 4 |
+-------+------+
SELECT score,
(SELECT COUNT(DISTINCT score)
FROM scores WHERE score>=s.score) RANK
FROM scores s ORDER BY score DESC;
项目十:行程和用户(难度:困难)
Trips 表中存所有出租车的行程信息。
每段行程有唯一键 Id,Client_Id 和 Driver_Id 是 Users 表中 Users_Id 的外键。
Status 是枚举类型,枚举成员为 (‘completed’, ‘cancelled_by_driver’, ‘cancelled_by_client’)。
+----+-----------+-----------+---------+--------------------+----------+
| Id | Client_Id | Driver_Id | City_Id | Status |Request_at|
| 1 | 1 | 10 | 1 | completed |2013-10-01|
| 2 | 2 | 11 | 1 | cancelled_by_driver|2013-10-01|
| 3 | 3 | 12 | 6 | completed |2013-10-01|
| 4 | 4 | 13 | 6 | cancelled_by_client|2013-10-01|
| 5 | 1 | 10 | 1 | completed |2013-10-02|
| 6 | 2 | 11 | 6 | completed |2013-10-02|
| 7 | 3 | 12 | 6 | completed |2013-10-02|
| 8 | 2 | 12 | 12 | completed |2013-10-03|
| 9 | 3 | 10 | 12 | completed |2013-10-03|
| 10 | 4 | 13 | 12 | cancelled_by_driver|2013-10-03|
+----+-----------+-----------+---------+--------------------+----------+
Users 表存所有用户。
每个用户有唯一键 Users_Id。
Banned 表示这个用户是否被禁止,Role 则是一个表示(‘client’, ‘driver’, ‘partner’)的枚举类型。
+----------+--------+--------+
| Users_Id | Banned | Role |
| 1 | No | client |
| 2 | Yes | client |
| 3 | No | client |
| 4 | No | client |
| 10 | No | driver |
| 11 | No | driver |
| 12 | No | driver |
| 13 | No | driver |
+----------+--------+--------+
写一段 SQL 语句查出 **2013年10月1日 **至 **2013年10月3日 **期间非禁止用户的取消率。
基于上表,你的 SQL 语句应返回如下结果,取消率(Cancellation Rate)保留两位小数。
+------------+-------------------+
| Day | Cancellation Rate |
| 2013-10-01 | 0.33 |
| 2013-10-02 | 0.00 |
| 2013-10-03 | 0.50 |
+------------+-------------------+