1.了解SQL
1.1数据库 基础
1.1.1数据库database
保存有组织的数据的容器,通常是一个文件或者一组文件
DBMS数据库管理系统,即我们常说的数据库管理软件,数据库是DBMS创建和操纵的容器。
1.1.2表table
某种特定类型数据的结构化清单(储存在表中的数据是同一种类型的数据或清单)
模式(schema):用来描述数据库中特定的表,也可以用来描述整个数据库和其中标的关系。
1.1.3列和数据类型
列(column):
数据类型(datatype):所允许的数据的类型,每个表列都有相应的数据类型,它限制(或允许)该列中存储的数据。
1.1.4行row
表中的一个记录
1.1.5主键primary key
表中的每一行都应该有一列(或几列)可以唯一标识自己。唯一标识表中每行的这个列(或这几列)称为主键。
主键用来更新或者删除表中特定行。
表中任何列都能作为主键,要满足一下条件:
1.任意两行都不具有相同的主键值
2.每一行都必须具有一个主键值(主键列不允许为NULL)
3.主键列中的值不允许修改或者更新
4.主键不能重用(如果某行从表中删除,其主键不能赋给以后的新行)
2.检索数据
2.1SELECT语句
关键字(keyword):作为SQL组成部分的保留字。关键字不能作为表或列的名字。
2.2检索单个列
SELECT prod_name FROM products;
每个语句以;结束。
SQL不区分大小写,但是为了区别,对关键字用大写,表名列名用大写。
不区分空格,多个语句可以写在一行。但分开写更好。
2.3检索多个列
SELECT prod_id,prod_name,prod_price FROM products;
列名之间加逗号,但是列名的最后一个不加。
2.4检索所有列
SELECT * FROM products;
2.5检索不同的值
SELECT vend_id FROM products;
去重:
SELECT DISTINCT vend_id FROM products;
DISTINCT作用于其后的所有列
2.6限制结果
返回某一行或者一定数量的行
SQL Server 和Access中:
SELECT TOP 5 prod_name FROM products;
DB2:
SELECT prod_name FROM products FETCH FIRST 5 ROWS ONLY;
2.7注释
行内注释:
SELECT prod_name FROM products; --这是一条注释
#这是一条注释
SELECT prod_name FROM products;
多行注释:
/*SELECT prod_id,prod_name,prod_price
FROM products;*/
SELECT prod_name FROM products;
3.排序检索数据
3.1排序 ORDER BY
SELECT prod_name FROM products;
子句(clause):SQL语句由子句组成,有些必需,有些可选。一个字子句由一个关键字加上所提供的数据组成。
SELECT prod_name
FROM products
ORDER BY prod_name;
ORDER BY 应该是SELECT中最后一条子句
3.2按多个列排序
SELECT prod_id,prod_price,prod_name
FROM products
ORDER BY prod_price,prod_name;
当prod_price值相同时,才会按prod_name排序,否则将不会按prod_name进行排序。
3.3按列位置排序
SELECT prod_id,prod_price,prod_name
FROM products
ORDER BY 2,3;
3.4指定排序方向
默认为升序排列A~Z,降序指定DESC
SELECT prod_id,prod_price,prod_name
FROM products
ORDER BY prod_price DESC;
DESC只指定位于其前面的一个列名
如想对多个列进行降序排列,对每个列后加DESC.
一般认为a与A相同,若想改变,需找数据库管理员
4过滤数据
4.1WHERE子句
过滤条件:只检索所需数据
SELECT prod_price,prod_name
FROM products
WHERE prod_price=3.49;
返回prod_price为3.49的行,该行包含两个列。
ORDER BY 语句应该位于WHERE之后
4.2WHERE子句操作符
= 等于 < >不等于 !=不等于 < <= !< > >= !> BETWEEN
IS NULL 为NULL值
4.2.1检查单个值
SELECT prod_price,prod_name
FROM products
WHERE prod_price<10;
4.2.2不匹配查询
SELECT vend_id,prod_name
FROM products
WHERE vend_id <> ' DLL01 ';
单引号用来限定字符串
4.2.3范围值检测
SELECT prod_price,prod_name
FROM products
WHERE prod_price BETWEEN 5 AND 10;
4.2.4空值检查
SELECT prod_price,prod_name
FROM products
WHERE prod_price IS NULL;
5.高级数据过滤
5.1组合WHERE子句
操作符(operator):用来联结或改变WHERE子句中的关键字,也称为逻辑操作符(logical operator)
5.1.1AND 操作符(交)
SELECT prod_id,prod_price,prod_name
FROM products
WHERE vend_id =' DLL01 ' AND prod_price IS NULL;
5.1.2OR操作符(并)
SELECT prod_price,prod_name
FROM products
WHERE vend_id =' DLL01 ' OR prod_price IS NULL;
5.1.3求值顺序
SELECT prod_price,prod_name
FROM products
WHERE vend_id =' DLL01 ' OR vend_id =' BRS01 ' AND prod_price >=10;
BRS01制造的价格为10美元以上的所有产品,以及DLL01制造的所有产品。
AND的优先级高于OR
SELECT prod_price,prod_name
FROM products
WHERE (vend_id =' DLL01 ' OR vend_id =' BRS01 ') AND prod_price >=10;
()的优先级最高
5.2IN操作符
用来指定条件范围,范围中的每个条件都可以进行匹配。IN取一组有逗号分隔,括在()中的合法值。
SELECT prod_price,prod_name
FROM products
WHERE vend_id IN (' DLL01 ' , ' BRS01 ')
ORDER BY prod_name;
--检索DLL01和BRS01制造的所有产品
IN简化了OR语法,且IN可以包含其他SELECT语句
5.3NOT操作符
WHERE子句中用来否定其后条件的关键字,NOT总是与其他操作符一起使用
SELECT prod_name
FROM products
WHERE NOT vend_id =' DLL01 ' --相当于WHERE vend_id <>' DLL01 '
ORDER BY prod_name;
6.用通配符进行过滤
6.1LIKE操作符
通配符(wildcard):用来匹配值的一部分的特殊字符
搜索模式(search pattern)由字面值,通配符或两者组合的搜索条件
通配符搜索只能用于文本字段(字符串),非文本数据类型不能用通配符搜索
为在搜索子句中使用通配符,必须使用LIKE操作符
6.1.1%通配符
%表示任何字符出现任意次数。
SELECT prod_id,prod_name
FROM products
WHERE prod_name LIKE 'fish%' ; --找出所有以fish开头的产品
区分大小写,Fish就不匹配
SELECT prod_id,prod_name
FROM products
WHERE prod_name LIKE '%fish%' ;--中间为fish的产品
SELECT prod_id,prod_name
FROM products
WHERE prod_name LIKE 'f%h' ; --以f开头,h结尾的产品
WHERE prod_name LIKE 'f%h%' ; --以f开头,空格结尾的产品
--查找电子邮件 WHERE email LIKE 'b%@forta.com' ;
%还能匹配0个字符,但不能匹配NULL
6.1.2下划线(_)通配符
同%一样,但只匹配单个字符
SELECT prod_id,prod_name
FROM products
WHERE prod_name LIKE '__ inch teddy bear' ;
6.1.3方括号([])通配符
用来指定一个字符集,必须匹配指定位置(通配符位置)的一个字符
SELECT cust_contact
FROM customers
WHERE cust_contact LIKE '[JM]%' --找出名字以J或M开头的联系人
ORDER BY cust_contact;
否定形式
SELECT cust_contact
FROM customers
WHERE cust_contact LIKE '[^JM]%' --找出名字不是以J或M开头的联系人
--相当于WHERE NOT cust_contact LIKE '[JM]%'
ORDER BY cust_contact;
不用过多使用通配符,相同作用下有限使用通配符
7.创建计算字段
7.1计算字段
通过检索出转换,计算或格式化过的数据,而非直接检索。
字段(field)
在SQL语句中 可以完成的许多转换和格式化工作都可以直接在客户端应用程序内完成。
7.2拼接字段
拼接(concatenate):将值连接到一起(一个值附加到另一个值上)构成单个值。
vendors表包含供应商名和地址信息。假如要生成一个供应商报表,需要在格式化的名称(位置)中列出供应商的位置。此报表需要一个值,而表中数据存储在两个列vend_name和vend_country中。
操作符为(+)或者(||)
SELECT vend_name + ‘(‘+vend_country+’)’
FROM vendors
ORDER BY vend_name;
在MySQL或MariaDB中
SELECT contact(vend_name ,‘(‘,vend_country,’)’)
FROM vendors
ORDER BY vend_name;
由于数据库中一般填充为列宽的文本值,拼接后会产生空格,用RTIRIM()去除空格
SELECT RTIRIM(vend_name) + ‘(‘+RTIRIM(vend_country)+’)’
FROM vendors
ORDER BY vend_name;
–RTIRIM()去掉字符串右边空格
–LTRIM()去掉左边空格
–TRIM()去掉左右空格
使用别名 AS
SELECT RIRIM(vend_name) + ‘(‘+RIRIM(vend_country)+’)’
AS vend_title
FROM vendors
ORDER BY vend_name;
7.3执行算术计算
对检索出的数据进行算术计算
SELECT prod_id,quality,item_price
FROM orderitems
WHERE order_num=20008;
SELECT prod_id,
quality,
item_price,
quantity*item_price AS expanded_price
FROM orderitems
WHERE order_num=20008;
测试计算:
SELECT 3*2;
SELECT now();
SELECT trim('abc')
8.使用函数处理数据
每一个DBMS都有特定的函数,只有少数几个函数被主要的DBMS等同支持,与SQL语句一样,SQL函数是不可移植的
8.2大多数DBMS支持以下函数
1.处理文本字符串
2.对数据进行运算操作
3.处理日期和时间值并从这些值中提取特定成分的日期和时间函数
4.返回DBMS正使用的特殊信息的系统函数
8.2.1文本处理函数
SELECT vend_name,UPPER(vend_name) AS vend_name_upcase
FROM vendors
ORDER BY vend_name;
--UPPER将文字转换为大写
LEFT() 返回字符串左边的字符
LENGTH()
LOWER()
LTRIM()
RIGHT() 返回字符串右边的字符
RTRIM()
SOUNDEX() 近似发音匹配
UPPER()
--SOUNDEX()
SELECT cust_name,cust_contact
FROM customers
WHERE cust_name='Michael Green';
SELECT cust_name,cust_contact
FROM customers
WHERE SOUNDEX(cust_name)=SOUNDEX('Michael Green');
8.2.2日期和时间处理函数
SELECT order_num
FROM orders
WHERE DATEPART (yy,order_date)=2012;
SELECT order_num
FROM orders
WHERE DATEPART ('yyyy',order_date)=2012;
DATEPART()中有两个参数,包括返回的成分和从中返回成分的日期。
8.2.3数值处理函数
ABS()
COS()
EXP() 返回一个数的指数值
PI() 返回圆周率
SIN()
SQRT()
TAN()
9.汇总数据
9.1聚集数据
1.确定表中行数(满足某个条件或者某个特定值的函数)
2.获得表中某些行的和
3.找出表列(或特定的行)的最大值,最小值,平均值
聚集函数(aggregate founction)
AVG()
COUNT()
MAX()
MIN()
SUM()
9.1.1 AVG()函数
返回所有列的平均值或特定行列的平均值
SELECT AVG(prod_price) AS avg_price
FROM products;
SELECT AVG(prod_price) AS avg_price
FROM products
WHERE vend_id='DLL01';
--AVG()只能用于单个列,且忽略NULL的行
9.1.2 COUNT()函数
确定表中行的数目或符合特定条件的行的数目
1.COUNT(*)对表中行的数目进行计数。无论列中包含的是空值还是非空值
2.COUNT(column)对特定列中具有值的行计数,忽略NULL值
SELECT COUNT(*) AS num_cust
FROM customers;
--对所有行进行计数
SELECT COUNT(cust_email) AS num_cust
FROM customers;
--只对具有电子邮件地址的客户计数
9.1.3 MAX()函数
返回列中的最大值
SELECT MAX(prod_price) AS max_price
FROM products;
--对于文本类数据,返回按该列排序后的最后一行,忽略列值为NULL的行
9.1.4 MIN()函数
与MAX()选相反
9.1.5 SUM()函数
返回指定列值的和
SELECT SUM(quantity) AS item_ordered
FROM orderitems
WHERE order_num=20005;
SELECT SUM(item_price*quantity) AS item_ordered
FROM orderitems
WHERE order_num=20005;
--返回物品价钱之和
9.2聚集不同值
1.对所有行执行计算,指定ALL参数或不指定参数
2.只包含不同的值,指定DISTINCT参数,去除了列中相同的数值
SELECT AVG(DISTINCT prod_price) AS avg_price
FROM products
WHERE vend_id='DLL01';
9.3组合聚集函数
SELECT COUNT(*) AS num_items,
MIN(prod_price) AS price_min,
MAX(prod_price) AS price_max,
AVG(prod_price)AS price_avg
FROM products;
10.分组数据
GROUP子句和HAVING子句
##10.1数据分组
将数据分为多个逻辑组,对每个组进行聚集计算
##10.2创建分组
利用GROUP BY 子句建立
SELECT vend_id,COUNT(*) AS num_prods
FROM products
GROUP BY vend_id;
一些规定:
1.GROUP BY 子句中列出的每一列都必须是检索列或有效的表达式。如果在SELECT中使用表达式,则必须在GROUP BY 子句中指定相同的表达式,不能使用别名。
2.除聚集函数语句外,SELECT语句中的每一列都必须在GROUP BY 子句中给出。
3.具有NULL值的行,则NULL将作为一个分组返回,若列中有多行NULL值,它们将分为一组
4.GROUP BY子句必须出现在WHERE子句之后,ORDER BY 子句之前。
##10.3过滤分组
WHERE过滤指定的是行而不是分组。SQL中用HAVING进行过滤分组。实际上,所有的WHERE都可以被HAVING替换。
SELECT cust_id,COUNT(*) AS orders
FROM orders
GROUP BY cust_id
HAVING COUNT(*) >=2;
--过滤了两个以上订单的那些分组
SELECT cust_id,COUNT(*) AS orders
FROM orders
WHERE prod_price>=4
GROUP BY cust_id
HAVING COUNT(*) >=2;
--列出具有两个以上产品且价格大于等于4的供应商
使用HAVING时必须结合GROUP BY 子句
10.4分组和排序
SELECT order_num,COUNT(*) AS items
FROM orderitems
GROUP BY order_num
HAVING COUNT(*)>=3;
--检索包含三个或更多物品 的订单号和订购物品的数目。
SELECT order_num,COUNT(*) AS items
FROM orderitems
GROUP BY order_num
HAVING COUNT(*)>=3
ORDER BY items,order_num;
--先过滤分组,再排序