SQL:查询语句

1. 基础查询

1.1 基础查询概述

  • 基础查询的基本语法为:select 查询列表 form 表名;
  • 查询的结果集是一个虚拟表,类似与Java中的System.out.println()
  • 进行基础查询的内容可以是:字段、表达式、常量、函数等

1.2 使用方法

  1. 查询常量

    SELECT 100;
    
  1. 查询表达式

    SELECT 100%3;
    
  1. 查询单个字段

    SELECT `last_name` FROM `employess`;
    
  1. 查询多个字段

    SELECT `last_name`,`email`,`employee_id` FROM employess;
    
  2. 查询所有字段

    SELECT * FROM employees;
    
  3. 查询函数

    SELECT DATABASE();
    SELECT VERSION();
    SELECT USER();
    
  4. 起别名

    #方式一:使用as关键字
    SELECT USER() AS 用户名;
    SELECT USER() AS '用户名';
    SELECT USER() AS "用户名";
    SELECT last_name AS "姓 名" FROM employess;
    
    #方式二:使用空格
    SELECT USER()  用户名;
    SELECT USER()  '用户名';
    SELECT USER()  "用户名";
    #当使用空格时必须用引号
    SELECT last_name  "姓 名" FROM employess;
    
  5. 拼接不同的列

    #使用拼接函数concat
    SELECT CONCAT(first_name,last_name) AS "姓名"
    FROM employess;
    
  6. 去除重复数据

    #使用去重函数distinct
    SELECT DISTINCT department_id FROM employess;
    
  7. 查看表结构

    #方式一
    DESC employees;
    
    #方式二
    SHOW COLUMNS FROM emloyees;
    
  8. 判断是否为空

    #ifnull(表达式1,表达式2)
    /*
    表达式1:可能为null的字段或表达式
    表达式2:如果表达式1为null,则最终显示的值
    */
    SELECT IFNULL(commission_pct,'') FROM employees;
    

2. 条件查询

2.1 条件查询概述

  • 条件查询的语法为:select 查询列表 from 表名 where 筛选条件;
  • 执行顺序为:form语句、where语句、select语句
  • 条件查询有三种方式:
    • 按关系表达式筛选:<、>、=、<=、>=、<>(不等于)
    • 按逻辑表达式筛选:and(与)、or(或)、not(非)
    • 模糊查询:like、in、between and、is null

2.2 使用方法

按关系表达式筛选

#案例1:查询部门编号不是100的员工信息
SELECT *
FROM employees
WHERE department_id <> 100;

#案例二:查询工资<15000的员工姓名、工资
SELECT last_name,salary
FROM employees
WHERE salary < 15000;

按逻辑表达式筛选

#案例一:查询部门编号不是50-100之间员工姓名、部门编号、邮箱
SELECT last_name,department_id,email
FROM employees
WHERE department_id>100 OR department_id<50;

#案例二:查询奖金率>0.03或者 员工编号在60-100之间的员工信心
SELECT *
FROM employees
WHERE commission_pct>0.03 OR (employee_id>=60 AND employee_id<=100);

模糊查询

  1. like:一般与通配符搭配使用,对字符型数据进行部分匹配查询,常见的通配符:
    • '_'任意单个字符
    • '%'任意多个字符
#案例一:查询姓名中包含字符a的员工信息
SELECT *
FROM employees
WHERE last_name LIKE '%a%';

#案例二:查询姓名中最后一个字符为a的员工信息
SELECT *
FROM employees
WHERE last_name LIKE '%a';

#案例三:查询姓名中第三个字符为a的员工信息
SELECT *
FROM employees
WHERE last_name LIKE '__a%';

#案例四:查询姓名中第二个字符为_的员工信息
SELECT *
FROM employees
WHERE last_name LIKE '_\_%';

SELECT *
FROM employees
#设置任意字符为转义符号
WHERE last_name LIKE '_$_%' ESCAPE '$';
  1. in:查询某字段的值是否属于指定的列表内
#案例一:查询部门编号是30、50、90的员工名、部门编号
SELECT last_name,department_id
FROM employees
WHERE department_id IN(30,50,90);

#案例二:查询公众编号不是SH_CLERK或IT_PROG的员工信息
SELECT *
FROM employees
WHERE job_id NOT IN ('SH_CLERK','IT_PROG');
  1. between and:判断某个字段的值是否介于xx之间
#案例一:查询部门编号是30-90之间的部门编号、员工姓名
SELECT department_id ,last_name
FROM employees
WHERE department_id BETWEEN 30 AND 90;

#案例二:查询年薪不是10000-20000之间的员工姓名、工资、年薪
SELECT last_name,salary,salary*12*(1+IFNULL(commission_pct,0))
FROM employees
WHERE salary*12*(1+IFNULL(commission_pct,0)) NOT BETWEEN 10000 AND 20000;
  1. is null:判断值是否null
    • =:只能判断普通内容
    • IS:只能判断NULL值
    • <=>:安全等于,既能判断普通内容,又能判断NULL值
#案例一:查询没有奖金的员工信息
SELECT *
FROM employees
WHERE commission_pct IS NULL;

#案例二:查询有奖金的员工信息
SELECT *
FROM employees
WHERE commission_pct IS NOT NULL;

3. 排序查询

3.1 排序查询概述

  • 条件查询的语法:select 查询列表 from 表名 where 筛选条件(可有可无) order by 排序列表
  • 执行顺序:from子句、where子句、select子句、order by子句
  • 特点:
    • 排序列表可以是单个字段、多个字段、表达式、函数、列数、以及以上组合
    • 升序,通过asc,默认行为
    • 降序,通过desc

3.2 使用方法

  1. 按单个字段查询
#案例:将员工编号>120的员工信息进行工资的升序
SELECT *
FROM employees
WHERE employee_id >120
ORDER BY salary;
  1. 按表达式排序
#案例:对有奖金的员工,按年薪降序
#也可以将年薪表达式起别名,直接在表达式后添加别名
SELECT salary*12*(1+IFNULL(commission_pct,0))
FROM employees
WHERE commission_pct
ORDER BY salary*12*(1+IFNULL(commission_pct,0)) DESC;
  1. 按函数的结果排序
#案例:按姓名的字数长度进行升序
SELECT last_name
FROM employees
ORDER BY LENGTH(last_name);
  1. 按多个字段排序
#案例:查询员工姓名、工资、部门编号,先按工资升序,再按部门编号降序
SELECT last_name,salary,department_id
FROM employees
ORDER BY salary ASC,department_id DESC;
  1. 按列数排序
#案例:按第二列排序
SELECT *
FROM employees
ORDER BY 2

4. 常见函数

4.1 字符函数

1. CONCAT 拼接字符
SELECT CONCAT('hello',first_name,last_name) FROM employees;

2. LENGTH 获取字节长度
SELECT LENGTH('hello,张三');

3. CHAR_LENGTH 获取字符长度
SELECT CHAR_LENGTH('hello,张三');

4. SUBSTR 截取子串
/*
注意:起始索引从1开始
substr(str,起始索引,截取的字符长度)
substr(str,起始索引) 将后面的字符串都截取
*/
SELECT SUBSTR('helloworld!',1,3);
SELECT SUBSTR('helloworld!',6);

5. INSTR 获取字符第一次出现的位置
SELECT INSTR('helloworldllold','ll')

6. TRIM 去除前后指定的字符,默认为空格
SELECT TRIM("  hello  world  ");
SELECT TRIM('x' FROM 'xxxxhelloxxxworldxxxx');

7. LPAD/RPAD 坐填充/右填充
SELECT LPAD('张三',10,'a'); #填充完毕后一共10个字符
SELECT RPAD('张三',10,'a'); 

8. UPPER/LOWER 变大写/变小写
SELECT UPPER('abc');
SELECT LOWER('ABC');

9. STRCMP 比较两个字符大小
#第一个字符大,返回1;第一个小,返回-1;相等,返回0
SELECT STRCMP('abc','aaa')

4.2 数学函数

1. ABS 绝对值
SELECT ABS(-12);

2. CEIL 向上取整 返回>=该参数的最小整数
SELECT CEIL(0.09);

3. FLOOR 向下取整 返回<=该参数的最大整数
SELECT FLOOR(0.09)

4. ROUND 四舍五入
SELECT ROUND(3.14);

5. TRUNCATE 截断
SELECT TRUNCATE(3.14);

6. MOD 取余
SELECT MOD(10,3);
SELECT 10%3;

4.3 日期函数

1. NOW 当前日期和时间
SELECT NOW();

2. CURDATE 当前日期
SELECT CURDATE();

3. CURTIME 当前时间
SELECT CURTIME();

4. DATEDIFF 日期之差
SELECT DATEDIFF('2020-8-19','2000-6-23');

5. DATE_FORMAT 将日期转换为固定格式
SELECT DATE_FORMAT('2000-6-23','%Y年%m月%d日 %H时%i分%s秒');

6. STR_TO_DATE 按指定格式解析字符串为日期类型
SELECT STR_TO_DATE('6/23 2000','%m/%d %Y');

4.4 流程控制函数

1. IF 函数
SELECT IF(100>9,'好','坏');

#案例:如果有奖金,则显示最终奖金,如果无,则显示0
SELECT IF(commission_pct IS NULL,0,salary*12*commission_pct)
FROM employees;


2. CASE 函数
情况1:类似switch语句,可以实现等值判断
CASE 表达式
WHEN 值1 THEN 结果1
WHEN 值2 THEN 结果2
...
ELSE 结果n
END

SELECT department_id,salary,
CASE department_id
WHEN 30 THEN salary*2
WHEN 50 THEN salary*3
WHEN 60 THEN salary*4
ELSE salary
END

情况2:类似多重IF语句,实现区间判断
CASE
WHEN 条件1 THEN 结果1
WHEN 条件2 THEN 结果2
...
ELSE 结果n
END

SELECT salary,
CASE 
WHEN salary>20000 THEN 'A'
WHEN salary>15000 THEN 'B'
WHEN salary>10000 THEN 'C'
ELSE 'D'
END grade
FROM employees;

5. 分组查询

5.1 分组函数

分组函数往往用于实现将一组数据进行统计计算,最终得到一个值,又称为聚合函数或统计函数

分组函数有:

  • sum(字段名):求和
  • avg(字段名):求平均值
  • max(字段名):求最大值
  • min(字段名):求最小值
  • count(字段名):计算非空字段值的个数
#案例1:查询员工信息表中,所有员工的工资和、工资平均值、
#最低工资、最高工资、有工资的个数

SELECT SUM(salary),AVG(salary),MIN(salary),MAX(salary),COUNT(salary)
FROM employees;

#count补充说明
#统计结果集的行数,推荐使用count(*)
SELECT COUNT(*) FROM employees;

5.2 分组查询

  • 分组查询语法:
    • select 查询列表,⑤
    • from 表名,①
    • where 筛选条件,②
    • group by 分组列表,③
    • having 分组后筛选,④
    • order by 排序列表;,⑥
  • 分组查询特点:
    • 查询列表是分组函数和被分组的字段
    • 分组前筛选放入where后,带有分组函数的筛选(分组后筛选)放入having
#案例1:查询每个工种的员工的平均工资
SELECT AVG(salary),job_id
FROM employees
GROUP BY job_id;

#案例2:查询每个领导手下有奖金的员工的平均工资
SELECT AVG(salary),manager_id
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY manager_id;

#案例3:领导编号>102,每个领导手下的最低工资大于5000的最低工资
SELECT MIN(salary),manager_id
FROM employees
WHERE manager_id>102
GROUP BY manager_id
HAVING MIN(salary)>5000

#案例4:查询没有奖金的员工的最高工资>6000的工种编号和最高工资,按最高工资升序
SELECT MAX(salary),job_id
FROM employees
WHERE commission_pct IS NULL
GROUP BY job_id
HAVING MAX(salary)>6000
ORDER BY MAX(salary) ASC;

#案例5:查询每个工种每个部门的最低工资,并按最低工资降序
SELECT MIN(salary),job_id,department_id
FROM employees
GROUP BY job_id,department_id;

6. 连接查询

6.1 连接查询概述

若一个查询同时涉及两个以上的表,则称为连接查询

连接查询是关系数据库中最主要的查询,包括:

  • 等值连接查询
  • 自然连接查询:自然连接是一种特殊的等值连接,它要求两个关系中进行比较的分量必须是同名的属性组,并且在结果中把重复的属性列去掉
  • 非等值连接查询
  • 自身连接查询:连接操作不仅可以在两个表之间进行,也可以是一个表与其自己进行连接,称为表的自身连接
  • 外连接查询:与内连接不同的是,外连接不只列出与连接条件相匹配的行,而是列出左表(左外连接时)、右表(右外连接时)或两个表(全外连接时)中所有符合搜索条件的数据行
  • 复合条件链接查询:连接操作除了可以是两表连接,一个表与自身连接外,还可以是两个以上的表进行连接

6.2 使用方法

等值与非等值连接查询

等值连接语法:

  • select 查询列表,⑥
  • from 表明1,表明2,表明3,...,①
  • where 等值连接的连接条件,②
  • and 筛选条件,③
  • group by 分组列表,④
  • having 分组后筛选,⑤
  • order by 排序列表,⑦

等值连接特点:

  • 多表等值连接的结果为多表的交集部分
  • 多表的顺序没有要求
  • 一般要为表起别名

当连接运算符为=时,称为等值连接,使用其他运算符称为非等值连接

#案例1:查询员工名和部门
#起别名后select语句只允许用别名,与执行顺序相关
SELECT e.`last_name`,d.`department_name`
FROM employees e,departments d
WHERE e.`department_id`=d.`department_id`;

#案例2:查询部门编号>100的部门名和所在的城市名
SELECT department_id,city
FROM departments d,locations l
WHERE d.`location_id`=l.`location_id`
AND d.`department_id`>100;

#案例3:查询每个城市的部门个数
SELECT COUNT(*),l.`city`
FROM departments d,locations l
WHERE d.`location_id`=l.`location_id`
GROUP BY l.`city`;

#案例4:查询每个工种的工种名和员工个数,并且按员工个数降序
SELECT job_title,COUNT(*)
FROM employees e,jobs j
WHERE e.`job_id`=j.`job_id`
GROUP BY job_title
ORDER BY COUNT(*) DESC;

#案例5:查询员工名、部门名和所在城市
SELECT last_name,department_name,city
FROM employees e,departments d,locations l
WHERE e.`department_id`=d.`department_id`
AND d.`location_id`=l.`location_id`;

7. 子查询

7.1 子查询概述

当一个查询语句中又嵌套了另一个完整的select语句,则被嵌套的select语句称为子查询或内查询,外面的select语句称为主查询或外查询

子查询不一定必须出现在select语句内部,只是出现在select语句内部的时候比较多

按子查询出现位置进行分类:

  • select后面:要求子查询结果为单行单列(标量子查询)
  • form后面:子查询的结果可以多行多列
  • where或having后面:子查询的结果必须为单列,分为单行子查询多行子查询
  • exist后面:子查询结果必须为单列(相关子查询)

子查询特点:

  • 子查询放在条件中,必须要求放在条件的右侧
  • 子查询一般放在小括号中
  • 子查询的执行顺序优先于主查询
  • 单行子查询对应单行操作符:>、<、>=、<=、=、<>
  • 多行子查询对应了多行操作符:any/some、all、in

7.2 使用方法

子查询放在where或having后面

  1. 单行子查询
#查询和Zlotkey相同部门的员工姓名和工资
SELECT last_name,salary
FROM employees
WHERE department_id = (
    SELECT department_id
    FROM employees
    WHERE last_name = 'Zlotkey'
);

#查询工资比公司平均工资高的员工的员工号,姓名和工资
SELECT employee_id,last_name,salary
FROM employees
WHERE salary >(
    SELECT AVG(salary)
    FROM employees
);
  1. 多行子查询

in:判断某字段是否在指定列表内

any/some:判断某字段的值是否满足其中任意一个

all:判断某字段的值是否满足里面所有的

#查询location_id是1400或1700的部门中的所有员工姓名
SELECT last_name
FROM employees
WHERE department_id IN (
    SELECT department_id
    FROM departments
    WHERE location_id IN(1400,1700)
);

#返回其他部门中比job_id为'IT_PROG'部门任一工资低的员工的
#员工号、姓名、job_id以及salary
SELECT employee_id,last_name,job_id,salary
FROM employees
WHERE salary < ANY(
    SELECT DISTINCT salary
    FROM employees
    WHERE job_id = 'IT_PROG'
);

#返回其他部门中比job_id为'IT_PROG'部门所有工资低的员工的
#员工号、姓名、job_id以及salary
SELECT employee_id,last_name,job_id,salary
FROM employees
WHERE salary < ALL(
    SELECT DISTINCT salary
    FROM employees
    WHERE job_id = 'IT_PROG'
);

子查询放在其他关键词后面

  1. 放在select后面
#查询部门编号是50的员工个数
SELECT(
    SELECT COUNT(*)
    FROM employees
    WHERE department_id = 50
);
  1. 放在from后面
#查询每个部门的平均工资的工资级别
SELECT dep_ag.department_id,dep_ag.ag,g.grade
FROM sal_grade g
JOIN(
    SELECT AVG(salary) ag,department_id
    FROM employees
    GROUP BY department_id
) dep_ag ON dep_ag.ag BETWEEN g.min_salary AND g.max_salary;
  1. 放在exist后面
# 查询有无名字叫'张三丰'的员工信息
SELECT EXISTS(
    SELECT *
    FROM employees
    WHERE last_name = '张三丰'
) 有无;

8. 分页查询

8.1 分页查询概述

当页面上的数据,一页显示不全,则需要分页显示

分页查询的sql命令请求数据库服务器——>服务器响应查询到的多条数据——>显示在前台页面

分页查询语法:

  • select 查询列表,⑤
  • from 表明1,表明2,表明3,...,①
  • where 等值连接的连接条件,②
  • group by 分组列表,③
  • having 分组后筛选,④
  • order by 排序列表,⑥
  • limit 起始条目索引,显示的条目数,⑦

分页查询特点:

  • 起始条目索引从0开始,如果不写,默认为0
  • 参数一:起始条目数,参数二:需要显示的条目数

8.2 使用方法

#查询员工信息表的前5条
#两者完全相同
SELECT * FROM employees LIMIT 0,5;
SELECT * FROM employees LIMIT 5;

#查询有奖金的,且工资较高的第11名到第20名
SELECT *
FROM employees
WHERE commission_pct IS NOT NULL
ORDER BY salary DESC
LIMIT 10,10;

假如要显示的页数是page,每页显示的条目数为size,则limt (page-1)size,size;*

9. union联合查询

当查询结果来自于多张表,但多张表之间没有关联,这个时候往往使用联合查询,也称为union查询

联合查询语法:

SELECT 查询列表 FROM 表1 WHERE 筛选条件……
        UNION
SELECT 查询列表 FROM 表1 WHERE 筛选条件……
#查询所有国家的年龄>20岁的用户信息
SELECT * FROM China WHERE age>20 UNION
SELECT * FROM USA WHERE age>20

要求多条查询语句的多条列数必须一致,且不同表的每一列必须对应上

union自动去重,在union后加all会取消去重

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342