文章目录
- 一、表操作
- 1、MySQL表数据类型
- 1.1、MySQL数据类型
- 1.2、MySQL数值数据类型
- 1.3、MySQL布尔数据类型
- 1.4、MySQL字符串数据类型
- 1.5、MySQL日期和时间数据类型
- 1.6、MySQL空间数据类型
- 1.7、JSON数据类型
- 2、用SQL语句创建表
- 2.1、语句解释
- 2.2、设定列类型 、大小、约束
- 2.3、设定主键
- 3、用SQL语句向表中添加数据
- 3.1、语句解释
- 3.2、多种添加方式(指定列名;不指定列名)
- 4、用SQL语句删除表
- 4.1、DELETE
- 4.2、DROP
- 4.3、TRUNCATE
- 4.4、不同方式的区别
- 5、用SQL语句修改表
- 5.1、修改列名
- 5.2、删除列
- 5.3、新建列
- 5.4、新建行
- 5.5、删除行
- 5.6、修改表中数据
- 6、作业
- 二、表联结
- 1、MySQL别名
- 2、INNER JOIN
- 3、LEFT JOIN
- 4、CROSS JOIN
- 5、自连接
- 6、UNION
- 7、以上几种方式的区别和联系
- 8、作业
一、表操作
1、MySQL表数据类型
1.1、MySQL数据类型
数据库表包含具有特定数据类型(如数字或字符串)的多个列。
MySQL提供更多的数据类型,而不仅仅是数字或字符串。
MySQL中数据类型都可以通过以下特征来确定:
- 它用来表示数据值。
- 占用的空间以及值是固定长度还是可变长度。
- 数据类型的值可以被索引。
- MySQL如何比较特定数据类型的值。
数据类型 | 指定值和范围 |
| String(0~255) |
| String(0~255) |
| String(0~255) |
| String(0~65536) |
| String(0~65536) |
| String(0~16777215) |
| String(0~16777215) |
| String(0~4294967295) |
| String(0~4294967295) |
| Integer(-128~127) |
| Integer(-32768~32767) |
| Integer(-8388608~8388607) |
| Integer(-214847668~214847667) |
| Integer(-9223372036854775808~9223372036854775807) |
| decimal(精确到23位小数) |
| decimal(24~54位小数) |
| 将 |
| YYYY-MM-DD |
| YYYY-MM-DD HH:MM:SS |
| YYYYMMDDHHMMSS |
| HH:MM:SS |
| 选项值之一 |
| 选项值子集 |
| tinyint(1) |
1.2、MySQL数值数据类型
数字类型 | 描述 |
TINYINT | 一个很小的整数 |
SMALLINT | 一个小的整数 |
MEDIUMINT | 一个中等大小的整数 |
INT | 一个标准整数 |
BIGINT | 一个大整数 |
DECIMAL | 定点数 |
| 单精度浮点数 |
| 双精度浮点数 |
BIT | 一个字节字段 |
1.3、MySQL布尔数据类型
MySQL没有内置的`BOOLEAN`或`BOOL`整数,所以要表示布尔值,MySQL使用最小的整数类型。也就是`TINYINT(1)`。
换句话说,`BOOLEN`和`BOOL`是`TINYINT(1)`的同义词。
1.4、MySQL字符串数据类型
在MySQL中,字符串可以容纳从纯文本到二进制数据(如图像或文件)的任何内容。
可以通过使用`LIKE`运算符,正则表达式和全文搜索,根据模式来比较和搜索字符串。
字符串类型 | 描述 |
char | 固定长度的非二进制(字符)字符串 |
varchar | 可变长度的非二进制字符串 |
| 一个固定长度的二进制字符串 |
| 一个可变长度的二进制字符串 |
| 一个非常小的BLOB(二进制大对象) |
| 一个小的BLOB(二进制大对象) |
| 一个中等大小的BLOB(二进制大对象) |
| 一个大的BLOB(二进制大对象) |
TINYTEXT | 一个非常小的非二进制字符串 |
TEXT | 一个小的非二进制字符串 |
MEDIUMTEXT | 一个中等大小的非二进制字符串 |
LONGTEXT | 一个很大的非二进制字符串 |
ENUM | 枚举; 每个列值可以被分配一个枚举成员 |
| 集合; 每个列值可以分配零个或多个 |
1.5、MySQL日期和时间数据类型
MySQL提供日期和时间的类型以及日期和时间的组合。
此外,MySQL还支持时间戳数据类型,用于跟踪表的一行中的更改。
如果只想存储没有日期和月份的年份数据,则可以使用`YEAR`数据类型。
字符串类型 | 描述 |
DATE |
|
TIME |
|
DATETIME |
|
TIMESTAMP |
|
|
|
1.6、MySQL空间数据类型
字符串类型 | 描述 |
GEOMETRY | 任何类型的空间值 |
POINT | 一个点(一对X-Y坐标) |
LINESTRING | 曲线(一个或多个POINT值) |
POLYGON | 多边形 |
GEOMETRYCOLLECTION |
|
MULTILINESTRING |
|
MULTIPOINT |
|
MULTIPOLYGON |
|
1.7、JSON数据类型
2、用SQL语句创建表
2.1、语句解释
创建新表:CERATE TABLE
语句
简单的形式说明语法:
CERATE TABLE [IF NOT EXISTS] table_name(
column_list
)engine=table_type;
- 首先,指定
CERATE TABLE
子句之后创建的表名称。表名在数据库中必须是唯一的。IF NOT EXISTS
是语句的可选部分,允许检查正在创建的表是否存在于数据库中。如果存在,MySQL会忽略整个语句,不会创建任何新的表。建议使用。 - 其次,在
column_list
部分指定表的列表。字段的列用逗号(,
)分隔。 - 需要为
engine
子句中的表指定存储引擎。可以使用任何引擎,默认使用InnoDB。
2.2、设定列类型 、大小、约束
column_name_data_type[size] [NOT NULL|NULL] [DEFAULT value]
[AUTO_INCREMENT]
-
column_name
指定列的名称。每列具有特定数据类型和大小,例如:VARCHAR(255)
。 -
NOT NULL
或者NULL
表示该列是否接受NULL
值。 -
DEFAULT
值用于指定列的默认值。 -
AUTO_INCREMENT
指示每当将新行插入到表中时,列的值会自动增加。每个表都有一个且只有一个AUTO_INCREMENT
列。
2.3、设定主键
使用以下语法:
PRIMARY KEY (col1,col2,col3,……)
数据库创建示例:
3、用SQL语句向表中添加数据
3.1、语句解释
使用INSERT
关键字。INSERT
语句的语法:
INSERT INTO table(column1,column2,……)
VALUES(value1,value2,……);
- 在
INSERT INTO
子句之后,在括号内指定表名和逗号分隔列的列表。 - 将括号内的相应列的逗号分隔值放在
VALUES
关键字之后。
3.2、多种添加方式(指定列名;不指定列名)
指定列名
INSERT INTO tasks(SUBJECT,start_date,end_date,description)
VALUES('Learn MySQL INSERT','2017-07-21','2017-07-22','Start learning..');
SELECT * FROM tasks;
查询结果:
不指定列名
为表中所有列指定相应列的值,可以不指定列名添加。
INSERT INTO tasks
VALUES('Learn MySQL INSERT','2017-07-21','2017-07-22','Start learning..');
SELECT * FROM tasks;
与上方效果相同。
4、用SQL语句删除表
4.1、DELETE
语法:
DELETE FROM table_name
WHERE condition;
- 指定删除数据的表(
table_name
) - 使用条件来指定要在
WHERE
子句中删除的行记录。如果行匹配条件,这些行记录将被删除。省略WHERE子句,DELETE语句将删除表中的所有行。
除了删除数据外,DELETE
语句返回删除的行数。
限制删除的行数:
DELETE FROM table
LIMIT row_count;
请注意,表中的行顺序未指定,因此,当使用LIMIT子句时,应始终使用ORDER BY子句,不然删除的记录可能不是预期的那样。
4.2、DROP
删除数据库DROP DATABASE
DROP DATABASE [IF EXISTS] database_name;
删除数据库意味着数据库中的所有数据和关联对象将被永久删除,并且无法撤销。IF EXISTS
是该语句的可选部分,以防止您删除数据库服务器中不存在的数据库。
4.3、TRUNCATE
TRUNCATE table_name;
清除表内内容,保留表结构。
4.4、不同方式的区别
- 需要永久删除,使用
DROP
。 - 只需要删除表内内容,保留表结构,使用
TRUNCATE
。 - 删除部分记录,使用
DELETE
。
5、用SQL语句修改表
使用ALTER TABLE
更改现有表的结构。
ALTER TABLE table_name action1[,action2,…]
- 在
ALTER TABLE
子句之后指定要更改的表名称。 - 列出一组要应用于该表的操作。操作可以是添加新列,添加主键,重命名表等任何操作。
ALTER TABLE
语句允许在单个ALTER TABLE语句中应用多个操作,每个操作由逗号(,)分隔。
5.1、修改列名
ALTER TABLE table_name
CHANGE 原列名 新列名 数据类型 约束;
慎重使用,注意数据类型不能省略。
5.2、删除列
ALTER TABLE table_name
DROP COLUMN 列名;
5.3、新建列
ALTER TABLE table_name
ADD COLUMN 列名 数据类型;
可以使用FIRST
与ALTER 列名
指定新建列的位置。
5.4、新建行
使用INSERT INTO
语句。
5.5、删除行
使用DELETE WHERE
语句。
5.6、修改表中数据
UPDATE table_name
SET 列1=值1,列2=值2
WHERE 条件;
6、作业
//创建course表,有student学生和class班级字段
CREATE TABLE course(
student VARCHAR(10),
class VARCHAR(10)
);
//插入数据
INSERT INTO course
VALUES
('A','Math'),
('B','English'),
('C','Math'),
('D','Biology'),
('E','Math'),
('F','Computer'),
('G','Math'),
('H','Math'),
('I','Math'),
('A','Math');
//查询结果
SELECT * FROM course;
+---------+----------+
| student | class |
+---------+----------+
| A | Math |
| B | English |
| C | Math |
| D | Biology |
| E | Math |
| F | Computer |
| G | Math |
| H | Math |
| I | Math |
| A | Math |
+---------+----------+
//查询所有超过或等于5名学生的课程(学生在每个课中不应被重复计算)
SELECT class FROM course GROUP BY class
HAVING COUNT(DISTINCT student) >= 5;
+-------+
| class |
+-------+
| Math |
+-------+
//创建一个salary表,有m=男性和f=女性的值。
CREATE TABLE salary(
id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
NAME VARCHAR(10) NOT NULL,
sex CHAR(2) NOT NULL,
salary VARCHAR(10) NOT NULL
);
INSERT INTO salary
VALUES
(1,'A','m',2500),
(2,'B','f',1500),
(3,'C','m',5500),
(4,'D','f',500);
SELECT * FROM salary;
+----+------+-----+--------+
| id | name | sex | salary |
+----+------+-----+--------+
| 1 | A | m | 2500 |
| 2 | B | f | 1500 |
| 3 | C | m | 5500 |
| 4 | D | f | 500 |
+----+------+-----+--------+
//交换所有的f值和m值
//第一种方法
UPDATE salary SET sex = (
CASE sex
WHEN 'f'
THEN 'm'
WHEN 'm'
THEN 'f'
END
);
SELECT * FROM salary;
+----+------+-----+--------+
| id | name | sex | salary |
+----+------+-----+--------+
| 1 | A | f | 2500 |
| 2 | B | m | 1500 |
| 3 | C | f | 5500 |
| 4 | D | m | 500 |
+----+------+-----+--------+
//第二种方法
UPDATE salary SET sex = IF(
sex = 'm','f','m'
);
SELECT * FROM salary; //与上面的结果比较
+----+------+-----+--------+
| id | name | sex | salary |
+----+------+-----+--------+
| 1 | A | m | 2500 |
| 2 | B | f | 1500 |
| 3 | C | m | 5500 |
| 4 | D | f | 500 |
+----+------+-----+--------+
二、表联结
1、MySQL别名
通过使用SQL语言,可以为表名称或列名称指定别名。使用AS
关键字。
创建别名是为了让列名称的可读性更强。
//列的SQL别名语法:
SELECT column_name AS alias_name//提示:如果列名称包含空格,要求使用双引号或方括号
FROM table_name;
//表的 SQL 别名语法:
SELECT column_name(s)
FROM table_name AS alias_name;
//列的别名示例1:指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。
SELECT name AS n, country AS c
FROM Websites;
//列的别名示例2:把三个列(url、alexa 和 country)结合在一起,并创建一个名为 "site_info" 的别名。
SELECT name, CONCAT(url, ', ', alexa, ', ', country) AS site_info
FROM Websites;
//表的别名实例:使用 "Websites" 和 "access_log" 表,并分别为它们指定表别名 "w" 和 "a"(通过使用别名让 SQL 更简短):
SELECT w.name, w.url, a.count, a.date
FROM Websites AS w, access_log AS a
WHERE a.site_id=w.id and w.name="教程";
//如果不使用别名:(与上面SQL语句效果相同)
SELECT Websites.name, Websites.url, access_log.count, access_log.date
FROM Websites, access_log
WHERE Websites.id=access_log.site_id and Websites.name="教程";
在以下情况中应使用别名:
- 在查询中涉及超过一个表
- 在查询中使用了函数
- 列名称很长或者可读性差
- 需要把两个列或者多个列结合在一起
2、INNER JOIN
内连接或等值连接,获取两个表中字段匹配关系的记录。
//在RUNOOB数据库中存在这样两张表:
mysql> use RUNOOB;
Database changed
mysql> show tables;
+------------------+
| Tables_in_runoob |
+------------------+
| runoob_tbl |
| tcount_tbl |
+------------------+
2 rows in set (0.01 sec)
mysql> select * from tcount_tbl;
+---------------+--------------+
| runoob_author | runoob_count |
+---------------+--------------+
| 菜鸟教程 | 10 |
| RUNOOB.COM | 20 |
| Google | 22 |
+---------------+--------------+
3 rows in set (0.00 sec)
mysql> select * from runoob_tbl;
+-----------+---------------+---------------+-----------------+
| runoob_id | runoob_title | runoob_author | submission_date |
+-----------+---------------+---------------+-----------------+
| 1 | 学习 PHP | 菜鸟教程 | 2017-04-12 |
| 2 | 学习 MySQL | 菜鸟教程 | 2017-04-12 |
| 3 | 学习 Java | RUNOOB.COM | 2015-05-01 |
| 4 | 学习 Python | RUNOOB.COM | 2016-03-06 |
| 5 | 学习 C | FK | 2017-04-05 |
+-----------+---------------+---------------+-----------------+
5 rows in set (0.00 sec)
//使用MySQL的INNER JOIN(也可以省略 INNER 使用 JOIN,效果一样)来连接以上两张表来读取runoob_tbl表中所有runoob_author字段在tcount_tbl表对应的runoob_count字段值:
mysql> select a.runoob_id,a.runoob_author,b.runoob_count
-> from runoob_tbl a
-> inner join tcount_tbl b
-> on a.runoob_author = b.runoob_author;
+-----------+---------------+--------------+
| runoob_id | runoob_author | runoob_count |
+-----------+---------------+--------------+
| 1 | 菜鸟教程 | 10 |
| 2 | 菜鸟教程 | 10 |
| 3 | RUNOOB.COM | 20 |
| 4 | RUNOOB.COM | 20 |
+-----------+---------------+--------------+
4 rows in set (0.01 sec)
3、LEFT JOIN
左连接,获取左表中所有记录,即使右表没有对应匹配的记录。
//以 runoob_tbl 为左表,tcount_tbl 为右表
mysql> select a.runoob_id,a.runoob_author,b.runoob_count
-> from runoob_tbl a
-> left join tcount_tbl b
-> on a.runoob_author = b.runoob_author;
+-----------+---------------+--------------+
| runoob_id | runoob_author | runoob_count |
+-----------+---------------+--------------+
| 1 | 菜鸟教程 | 10 |
| 2 | 菜鸟教程 | 10 |
| 3 | RUNOOB.COM | 20 |
| 4 | RUNOOB.COM | 20 |
| 5 | FK | NULL |
+-----------+---------------+--------------+
5 rows in set (0.00 sec)
4、CROSS JOIN
CROSS JOIN
将返回第一个表中的每一行与第二个表中的每一行组合在一起的所有记录。这也意味着CROSS JOIN
返回连接表中行集的笛卡尔积。CROSS JOIN
使用:可以以两种方式来指定JOIN
或语法通过列出在表FROM
由逗号分隔的条款,而无需使用WHERE
子句供给联接标准。SQL CROSS JOIN
语法:
SELECT * FROM [表1] CROSS JOIN [表2]
或
SELECT * FROM [表1],[表2]
mysql> select * from runoob_tbl cross join tcount_tbl;
+-----------+---------------+---------------+-----------------+---------------+--------------+
| runoob_id | runoob_title | runoob_author | submission_date | runoob_author | runoob_count |
+-----------+---------------+---------------+-----------------+---------------+--------------+
| 1 | 学习 PHP | 菜鸟教程 | 2017-04-12 | 菜鸟教程 | 10 |
| 1 | 学习 PHP | 菜鸟教程 | 2017-04-12 | RUNOOB.COM | 20 |
| 1 | 学习 PHP | 菜鸟教程 | 2017-04-12 | Google | 22 |
| 2 | 学习 MySQL | 菜鸟教程 | 2017-04-12 | 菜鸟教程 | 10 |
| 2 | 学习 MySQL | 菜鸟教程 | 2017-04-12 | RUNOOB.COM | 20 |
| 2 | 学习 MySQL | 菜鸟教程 | 2017-04-12 | Google | 22 |
| 3 | 学习 Java | RUNOOB.COM | 2015-05-01 | 菜鸟教程 | 10 |
| 3 | 学习 Java | RUNOOB.COM | 2015-05-01 | RUNOOB.COM | 20 |
| 3 | 学习 Java | RUNOOB.COM | 2015-05-01 | Google | 22 |
| 4 | 学习 Python | RUNOOB.COM | 2016-03-06 | 菜鸟教程 | 10 |
| 4 | 学习 Python | RUNOOB.COM | 2016-03-06 | RUNOOB.COM | 20 |
| 4 | 学习 Python | RUNOOB.COM | 2016-03-06 | Google | 22 |
| 5 | 学习 C | FK | 2017-04-05 | 菜鸟教程 | 10 |
| 5 | 学习 C | FK | 2017-04-05 | RUNOOB.COM | 20 |
| 5 | 学习 C | FK | 2017-04-05 | Google | 22 |
+-----------+---------------+---------------+-----------------+---------------+--------------+
15 rows in set (0.00 sec)
5、自连接
自连接就是同一张表的不同列连接在一起,也就是自我连接。
mysql> select a.runoob_id,a.runoob_author,b.runoob_count
-> from runoob_tbl a,tcount_tbl b
-> where a.runoob_author = b.runoob_author;
+-----------+---------------+--------------+
| runoob_id | runoob_author | runoob_count |
+-----------+---------------+--------------+
| 1 | 菜鸟教程 | 10 |
| 2 | 菜鸟教程 | 10 |
| 3 | RUNOOB.COM | 20 |
| 4 | RUNOOB.COM | 20 |
+-----------+---------------+--------------+
4 rows in set (0.00 sec)
6、UNION
MySQL UNION 操作符用于连接两个以上的 SELECT 语句的结果组合到一个结果集合中。多个 SELECT 语句会删除重复的数据。
//MySQL UNION 操作符语法格式:
SELECT expression1, expression2, ... expression_n
FROM tables
[WHERE conditions]
UNION [ALL | DISTINCT]
SELECT expression1, expression2, ... expression_n
FROM tables
[WHERE conditions];
参数:
- expression1, expression2, … expression_n: 要检索的列。
- tables: 要检索的数据表。
- WHERE conditions: 可选, 检索条件。
- DISTINCT: 可选,删除结果集中重复的数据。默认情况下 UNION 操作符已经删除了重复数据,所以 DISTINCT 修饰符对结果没啥影响。
- ALL: 可选,返回所有结果集,包含重复数据。
//从"runoob_tbl"表和"tcount_tbl"表中选取所有不同的runoob_author(只有不同的值):
mysql> select runoob_author from runoob_tbl
-> union
-> select runoob_author from tcount_tbl
-> order by runoob_author;
+---------------+
| runoob_author |
+---------------+
| FK |
| Google |
| RUNOOB.COM |
| 菜鸟教程 |
+---------------+
4 rows in set (0.01 sec)
//使用union all从"runoob_tbl"表和"tcount_tbl"表中选取所有的runoob_author(也有重复的值):
mysql> select runoob_author from runoob_tbl
-> union all
-> select runoob_author from tcount_tbl
-> order by runoob_author;
+---------------+
| runoob_author |
+---------------+
| FK |
| Google |
| RUNOOB.COM |
| RUNOOB.COM |
| RUNOOB.COM |
| 菜鸟教程 |
| 菜鸟教程 |
| 菜鸟教程 |
+---------------+
8 rows in set (0.00 sec)
7、以上几种方式的区别和联系
- INNER JOIN:内连接或等值连接,获取两个表中字段匹配关系的记录。
- LEFT JOIN:左连接,获取左表中所有记录,即使右表没有对应匹配的记录。
- CROSS JOIN:将返回第一个表中的每一行与第二个表中的每一行组合在一起的所有记录。笛卡尔积
- 自连接:同一张表的不同列连接在一起,也就是自我连接。
- UNION :用于连接两个以上的 SELECT 语句的结果组合到一个结果集合中。多个 SELECT 语句会删除重复的数据。
8、作业
mysql> use program;
Database changed
mysql> create table Person(
-> PersonId int(11) primary key,
-> FirstName varchar(10),
-> LastName varchar(10)
-> );
Query OK, 0 rows affected (0.82 sec)
mysql> desc Person;
+-----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| PersonId | int(11) | NO | PRI | NULL | |
| FirstName | varchar(10) | YES | | NULL | |
| LastName | varchar(10) | YES | | NULL | |
+-----------+-------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
mysql> create table Address(
-> AddressId int(11) primary key,
-> PersonId int(11),
-> City varchar(10),
-> State varchar(10)
-> );
Query OK, 0 rows affected (0.97 sec)
mysql> desc Address;
+-----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| AddressId | int(11) | NO | PRI | NULL | |
| PersonId | int(11) | YES | | NULL | |
| City | varchar(10) | YES | | NULL | |
| State | varchar(10) | YES | | NULL | |
+-----------+-------------+------+-----+---------+-------+
4 rows in set (0.01 sec)
mysql> insert into Person
-> values(1,'A1','B1'),(2,'A2','B2'),(3,'A3','B3');
Query OK, 3 rows affected (0.15 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from Person;
+----------+-----------+----------+
| PersonId | FirstName | LastName |
+----------+-----------+----------+
| 1 | A1 | B1 |
| 2 | A2 | B2 |
| 3 | A3 | B3 |
+----------+-----------+----------+
3 rows in set (0.00 sec)
mysql> insert into Address
-> values(1,2,'a1','b1'),(2,3,'a2','b2'),(3,1,'a3','b3');
Query OK, 3 rows affected (0.22 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from Address;
+-----------+----------+------+-------+
| AddressId | PersonId | City | State |
+-----------+----------+------+-------+
| 1 | 2 | a1 | b1 |
| 2 | 3 | a2 | b2 |
| 3 | 1 | a3 | b3 |
+-----------+----------+------+-------+
3 rows in set (0.00 sec)
//SQL查询,无论 person 是否有地址信息,都需要基于上述两表提供 person 的以下信息:FirstName, LastName, City, State
mysql> select p.FirstName,p.LastName,a.City,a.State
-> from Person p
-> left join Address a
-> on p.PersonId = a.PersonId;
+-----------+----------+------+-------+
| FirstName | LastName | City | State |
+-----------+----------+------+-------+
| A2 | B2 | a1 | b1 |
| A3 | B3 | a2 | b2 |
| A1 | B1 | a3 | b3 |
+-----------+----------+------+-------+
3 rows in set (0.00 sec)
//编写一个 SQL 查询,来删除 email 表中所有重复的电子邮箱,重复的邮箱里只保留 ID 最小 的那个。
mysql> select * from email;
+----+---------+
| ID | Email |
+----+---------+
| 1 | a@b.com |
| 2 | c@d.com |
| 3 | a@b.com |
+----+---------+
3 rows in set (0.30 sec)
mysql> delete e1 from email e1
-> left join email e2
-> on e1.Email = e2.Email
-> where e1.ID>e2.ID;
Query OK, 1 row affected (0.26 sec)
mysql> select * from email;
+----+---------+
| ID | Email |
+----+---------+
| 1 | a@b.com |
| 2 | c@d.com |
+----+---------+
2 rows in set (0.00 sec)