创建计算字段
计算字段
字段
: 基本上与列
的意思相同- 计算字段是运行时在
SELECT
语句内创建的
拼接字段
拼接
: 将值连接到一起. 将一个值附加到另一个值构成一个单值.操作符:
+
加号||
select vend_name || '(' || vend_country || ')' from Vendors;
函数
PTRIM()
: 去除值右边的所有的空格select RTRIM(vend_name ) || '(' || vend_country || ')' from Vendors;
执行算术计算
select prod_id ,quantity,item_price
from OrderItems
where order_num = 20008;
-- 用字段进行算术计算
select prod_id,quantity,item_price,
quantity*item_price as expanded_price
from OrderItems
where order_num = 20008;
使用函数处理数据
函数
- 大多数SQL实现支持以下类型的函数
- 处理文本字符串的文本函数
- 数值数据算数计算的数值函数
- 日期与时间函数
- 特殊系统函数
文本处理函数
UPPER
函数 : 将文本转成大写select vend_name,UPPER(vend_name) as vend_name_upcase from Vendors order by vend_name;
常用文本处理函数:
函数 | 说明 |
---|---|
LEFT | 返回字符串左边的字符 |
LENGTH | 返回字符串长度 |
LOWER | 转成小写 |
RIGHT | 返回字符串右边的字符 |
LTRIM | 去除字符串左边的空格 |
RTRIM | 去除字符串右边的空格 |
UPPER | 转成大写 |
SOUNDEX | 返回字符串的soundex值 |
- SOUNDEX 不一定支持
日期与时间处理函数
数组处理函数
函数 | 说明 |
---|---|
ABS | 绝对值 |
COS | 余弦 |
EXP | 指数 |
PI | π |
SIN | 正弦 |
SQRT | 平方根 |
TAN | 正切 |
汇总数据
聚集函数
函数 | 说明 |
---|---|
AVG | 返回某个列的平均值 |
COUNT | 返回某个列的行数 |
MAX | 返回某列的最大值 |
MIN | 返回某列的最小值 |
SUM | 返回某列的值之和 |
select AVG(prod_price) as avg_price
from Products;
组合聚类函数
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;
分组数据
- 两个
SELECT
语句子句:GROUP BY
和HAVING
子句 - 分组可以将数据分成多个逻辑组. 对每个组进行聚类计算.
创建分组
分组的使用
SELECT
子句GROUP BY
创建select vend_id,count(*) as num_prods from Products group by vend_id;
过滤分组
WHERE
过滤的是指定行而不是分组HAVING
子句 : 用于过滤分组HAVING
支持所有WHERE
操作符select cust_id ,count(*) as orders from Orders group by cust_id having count(*)>=2;
HAVING
和WHERE
的差别WHERE
在数据分组前进行过滤
WHERE
排除的行不包括在分组中,这可能会改变计算值.从而影响HAVING
分组过滤HAVING
数据分组后进行过滤
select vend_id,count(*) as num_prods from Products where prod_price >=4 group by vend_id having count(*) >=2; select vend_id,count(*) as num_prods from Products -- where prod_price >=4 group by vend_id having count(*) >=2;
分组与排序
ORDER BY
VSGROUP BY
order BY | GROUP BY |
---|---|
对产生的输出排序 | 对行分组 但输出可能不是分组的顺序 |
任意列都可以使用 | 只能使用选择列 or 表示式列 |
不一定需要 | 若何聚类函数一起使用,则必须使用 |
SELECT order_num, COUNT(*) AS items
FROM OrderItems
GROUP BY order_num
HAVING COUNT(*) >= 3
ORDER BY items, order_num;
SELECT
子句顺序
子句 | 说明 | 是否必须使用 |
---|---|---|
SELECT | 要返回的列or表达式 | 是 |
FROM | 从中检索数据的表 | 仅从表中选择数据时使用 |
WHERE | 行级过滤 | 否 |
GROUP BY | 分组说明 | 仅在按组计算聚类时使用 |
HAVING | 组级过滤 | 否 |
ORDER BY | 输出排序顺序 | 否 |
使用子查询
利用子查询进行过滤
- 子查询总是从内向外处理
SELECT cust_id
FROM Orders
WHERE order_num IN (SELECT order_num
FROM OrderItems
WHERE prod_id = 'RGAN01');
作为计算字段使用子查询
SELECT cust_name,
cust_state,
(SELECT COUNT(*)
FROM Orders
WHERE Orders.cust_id = Customers.cust_id) AS orders
FROM Customers
ORDER BY cust_name;
联接表
关系表
- 关系数据库的可收缩性远比非关系数据库要好.
为什么使用联结
- 数据分解为多个表能更有效地存储,更方便地处理,并且可伸缩性更好.但这些好处是有代价的.
联结
: 数据存储在多个表中. 用一条SELECT
语句就索引出数据!
创建联结
select vend_name,prod_name,prod_price
from Vendors,Products
where Vendors.vend_id=Products.vend_id;
- 与之前
SELECT
语句的最大差别在于第三句话. WHERE
子句的重要性:WHERE
子句作为过滤条件,只包含那些匹配给定条件(这里是联结条件)的行- 由没有
联结条件
的表关系返回的结果为 笛卡尔积. 检索出的行数为表一行数乘以表二行数.
内联结
内联结(inner join)
:等值联结
基于两个表之间的相等测试.两个表之间的关系是以
INNER JOIN
指定的部分FROM子句联结条件用
ON
子句SELECT vend_name, prod_name, prod_price FROM Vendors INNER JOIN Products ON Vendors.vend_id = Products.vend_id;
联结多个表
- 创建联结的基本规则相同。首先列出所有表,然后定义表之间的关系
select prod_name,vend_name,prod_price,quantity
from OrderItems,Products,Vendors
where Products.vend_id=Vendors.vend_id
and OrderItems.prod_id=Products.prod_id
and order_num = 20007; -- 过滤
子查询 与 联结
-- 子查询 SELECT cust_name, cust_contact FROM Customers WHERE cust_id IN (SELECT cust_id FROM Orders WHERE order_num IN (SELECT order_num FROM OrderItems WHERE prod_id = 'RGAN01')) -- 联结多个表 select cust_name,cust_contact from Customers,Orders,OrderItems where Customers.cust_id = Orders.cust_id and Orders.order_num = OrderItems.order_num and prod_id = 'RGAN01'
创建高级联接
使用表别名
使用别名引用被检索的表列. 给列起别名的语法如下:
select RTRIM(vend_name)+'('+RTRIM(vend_country)+')' as vend_tile from Vendors order by vend_name
SQL除了可以对列名和计算字段使用别名. 还允许给表明起别名.
- 缩短SQL语句
- 允许在一条
SELECT
语句中多次使用相同的表
select cust_name,cust_contact from Customers as C, Orders as O,OrderItems as OI where C.cust_id = O.cust_id and O.order_num = OI.order_num and prod_id = 'RGAN01'
使用表别名的一个主要原因是能在一条SELECT语句中不止一次引用相同的表
使用不同类型的联结
内联结
: 等值联结自联结(self-join)
:-- 子查询 select cust_id,cust_name,cust_contact from Customers where cust_name = (select cust_name from Customers where cust_contact = 'Jim Jones'); -- 自联结 -- Customers第一次出现用了别名C1,第二次出现用了别名C2 select c1.cust_id,c1.cust_name,c1.cust_contact from Customers as c1,Customers as c2 where c1.cust_name = c2.cust_name and c2.cust_contact='Jim Jones';
自然联结(natural join)
:标准的联结(eg.内联结)返回所有数据,相同的
列甚至多次出现.自然联结排除多次出现,使每一列只返回一次.
自然联结要求只能选择那些唯一的列.
一般通过对一个表使用通配符(SELECT *).而对其他表的列使用明确的子集来完成.
通配符只对第一个表使用.所有其他列明确列出,所以没有重复的列被检索出来 .
select c.*,o.order_num,o.order_date,oi.prod_id,oi.quantity,oi.item_price from Customers as c,Orders as o, OrderItems as oi where c.cust_id = o.cust_id and oi.order_num = o.order_num and prod_id = 'RGAN01';
外联结(outer join)
:许多联结将一个表中的行与另一个表中的行相关联,但有时候需要包含没有关联行的那些行 .
外联结
: 联结包含了那些在相关表中没有关联行的行
-- 内联结 它检索所有顾客及其订单 select Customers.cust_id , Orders.order_num from Customers inner join Orders on Customers.cust_id = Orders.cust_id; -- 外联结 要检索包括没有订单顾客在内的所有顾客 select Customers.cust_id , Orders.order_num from Customers left outer join Orders on Customers.cust_id = Orders.cust_id;
使用带聚集函数的联结
-- 检索出所有顾客以及每个顾客所下的订单数
select Customers.cust_id,count(Orders.order_num) as num_ord
from Customers inner join Orders
on Customers.cust_id = Orders.cust_id
group by Customers.cust_id;
-- 外联结时
select Customers.cust_id,count(Orders.order_num) as num_ord
from Customers left outer join Orders
on Customers.cust_id = Orders.cust_id
group by Customers.cust_id
组合查询
如何利用
UNION
操作将多条SELECT
语句合成一个结果集
- 多数的SQL查询只包换从一个或多个表中返回数据的单条
SELECT
语句. - 多条
SELECT
语句,并将结果作为一个查询结果集返回.这种组合查询通常称为并(union)或复合查询(compound query)
创建组合查询
使用
UNION
select cust_name,cust_contact,cust_email from Customers where cust_state in ('IL','IN','MI') union -- UNION指示DBMS执行这两条SELECT语句,并把输出组合成一个查询结果集 select cust_name,cust_contact,cust_email from Customers where cust_name = 'Fun4All'; -- 多个WHERE: select cust_name,cust_contact,cust_email from Customers where cust_state in ('IL','IN','MI') or cust_name = 'Fun4All';