----------------------------汇总数据---------------------------
--聚集函数用来汇总数据。由多种方法来返回所需的结果,高效,快速获得结果;
-- 37. 返回products 表中所有产品的平均价格
SELECT AVG(prod_price) AS avg_price
FROM products
-- 38. 返回products 表中供应商ID=1003所有产品的平均价格
SELECT AVG(prod_price) AS avg_price
FROM products
WHERE vend_id =1003
-- 39. 返回customers表中客户的总数
SELECT COUNT(*) as num_cust
FROM customers
-- 40. 返回customers表中有电子邮件地址的客户计数
SELECT COUNT(cust_email) as num_cust
FROM customers
-- 41. 返回products表中最贵的物品的价格
SELECT MAX(prod_price) AS max_price
FROM products
-- 42. 返回products表中最便宜的物品的价格
SELECT MIN(prod_price) AS max_price
FROM products
-- 43. 返回订单号=20005的所有物品数量之和,
SELECT SUM(quantity) AS items_ordered
FROM orderitems
WHERE order_num=20005;
-- 44. 返回订单号=20005的所有物品价钱之和,
SELECT SUM(item_price*quantity) AS total_price
FROM orderitems
WHERE order_num=20005;
-- 45. 聚集不同值,默认对所有行计算,可以指定ALL参数或不给参数
-- 对供应商ID=1003,并且只对有不同价格的商品进行平均计算
SELECT AVG(DISTINCT prod_price) AS avg_price
FROM products
WHERE vend_id =1003
-- 46. 组合聚集函数,可以包含多个聚集函数
-- 返回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
------------------------分组数据-----------------------
-- 47. 数据分组,并创建分组。 返回每个供应商提供的产品数目
SELECT vend_id, count(*) AS num_prods
FROM products
GROUP BY vend_id;
-- 结果
vend_id num_prods
1001 3
1002 2
1003 7
1005 2
-- 48. GROUP BY子句的一些重要的规定
-- GROUP BY 子句可以包含任意数目的列;
SELECT vend_id,count(*) AS num_prods
FROM products
GROUP BY vend_id;
SELECT vend_id,prod_id, count(*) AS num_prods
FROM products
GROUP BY vend_id,prod_id;
-- GROUP BY 子句可以指定多个分组,数据将在最后指定的分组上进行汇总;
SELECT vend_id,prod_id, count(*) AS num_prods
FROM products
GROUP BY vend_id,prod_id;
-- GROUP BY 子句列出的每个列都必须是检索列或有效的表达式(但不能是聚集函数),下面表达式是错误的;
SELECT vend_id,prod_id, count(*) AS num_prods
FROM products
GROUP BY vend_id,prod_id,num_prods;
-- GROUP BY 子句,除聚集计算语句外,SELECT语句中的每个列都必须在GROUP BY子句中给出;
SELECT vend_id,prod_id, count(*) AS num_prods
FROM products
GROUP BY vend_id,prod_id;
-- GROUP BY 子句,分组列中国具有NULL 值,则NULL将作为一个分组返回。如果列种有多行NULL值,它们将分为一组;
-- GROUP BY 子句,必须出现在WHERE子句之后,ORDER BY 子句之前;
SELECT vend_id,prod_id, count(*) AS num_prods
FROM products
GROUP BY vend_id,prod_id
ORDER BY vend_id,prod_id DESC
-- 49. 过滤分组,规定包括哪些分组,排除哪些分组;
--列出至少有两个订单的所有顾客
SELECT cust_id, COUNT(*) AS orders
FROM orders
GROUP BY cust_id
HAVING COUNT(*) >=2
--列出具有两个以上、价格为10以上的产品的供应商:
SELECT vend_id, COUNT(*) AS num_prods
FROM products
WHERE prod_price >= 10
GROUP BY vend_id
HAVING COUNT(*) > = 2
-- 50. 分组和排序,规定包括哪些分组,排除哪些分组;
ORDER BY: 排序产生的输出,任意列都可以使用(甚至未选择的列也可以使用),不一定需要
GROUP BY: 分组行。但输出可能不是分组的顺序,只可能使用选择列或表达式列,而且必须使用每个选择列表达式
--检索总计订单价格大于等于50的订单的订单号和总计订单价格
SELECT order_num,SUM(quantity*item_price) AS ordertotal
FROM orderitems
GROUP BY order_num
HAVING SUM(quantity*item_price)>=50
order_num ordertotal
20005 149.87
20006 55.00
20007 1000.00
20008 125.00
--检索总计订单价格大于等于50的订单的订单号和总计订单价格,按照总计订单价格排序输出
SELECT order_num,SUM(quantity*item_price) AS ordertotal
FROM orderitems
GROUP BY order_num
HAVING SUM(quantity*item_price)>=50
ORDER BY ordertotal
order_num ordertotal
20006 55.00
20008 125.00
20005 149.87
20007 1000.00
--SELECT 子句及其顺序
--SELECT 要返回的列或表达式,
--FROM 从中检索数据的表
--WHERE 行级过滤
--GROUP BY 分组说明
--HAVING 组级过滤
--ORDER BY 输出排序顺序
------------------------使用子查询-----------------------
-- 51. 检索返回订购物品TNT2的所有客户的ID
SELECT cust_id
FROM orders
WHERE order_num IN (SELECT order_num
FROM orderitems
WHERE prod_id ='TNT2')
--等价于
--检索包含物品TNT2的所有订单的编号
SELECT order_num
FROM orderitems
WHERE prod_id ='TNT2'
--检索具有订单编号为20005和20007的所有客户的ID
SELECT cust_id
FROM orders
WHERE order_num IN (20005,20007)
-- 52. 检索返回订购物品TNT2的所有客户的ID的客户信息
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 ='TNT2')
)
--结果:
--cust_name cust_contact
--Coyote Inc. Y Lee
--Yosemite Place Y Sam
-- 53 作为计算字段使用子查询
-- 对客户10001的订单进行计数
SELECT COUNT(*) AS orders
FROM orders
WHERE cust_id = 10001
-- 从customers表中检索客户列表,对检索出的每个客户,统计其在orders表中的订单数目
SELECT cust_name,
cust_state,
--下面SELECT 语句作为计算字段使用子查询
(SELECT COUNT(*)
FROM orders
where orders.cust_id = customers.cust_id) AS orders
FROM customers
ORDER BY cust_name
-- 54. 用子查询检查存在性,EXIST关键字,处理要比IN 语句快
-- 检索200509下订单的顾客的名字和ID
SELECT cust_id, cust_name
FROM customers
WHERE cust_id IN (SELECT cust_id
FROM orders
WHERE DATEDIFF(MONTH,order_date,'2005-09-01')=0
AND customers.cust_id=orders.cust_id)
--解释:先找出200509下订单的顾客ID,然后再根据这些顾客ID从customers表选择所需顾客;
--等价于:
SELECT cust_id, cust_name
FROM customers
WHERE EXISTS (
SELECT cust_id
--SELECT *
FROM orders
WHERE DATEDIFF(MONTH,order_date,'2005-09-01')=0
AND customers.cust_id=orders.cust_id)
-- 55. 检索除了200509下订单的顾客的名字和ID
SELECT customers.cust_id, customers.cust_name,orders.order_date
FROM customers
LEFT JOIN orders
on customers.cust_id=orders.cust_id
WHERE EXISTS (
SELECT cust_id
--SELECT *
FROM orders
WHERE DATEDIFF(MONTH,order_date,'2005-09-01')=0
AND customers.cust_id=orders.cust_id)
-- 子查询: 尽量不要嵌套太多的子查询,可以使用操作符IN,=,<>,尽量不要用SELECT *
--56.内部联结:检索200509下订单的顾客的名字和ID
SELECT customers.cust_id,customers.cust_name
FROM customers
INNER JOIN orders
ON customers.cust_id = orders.cust_id
WHERE DATEDIFF(MONTH,order_date,'2005-09-01')=0
SELECT customers.cust_id,customers.cust_name
FROM customers,orders
WHERE DATEDIFF(MONTH,order_date,'2005-09-01')=0
AND customers.cust_id = orders.cust_id
-- 子查询: 检索200509下订单的顾客的名字和ID
SELECT cust_id, cust_name
FROM customers
WHERE cust_id IN (SELECT cust_id
FROM orders
WHERE DATEDIFF(MONTH,order_date,'2005-09-01')=0
AND customers.cust_id=orders.cust_id)
-- 57.内部联结: 检索返回订购物品TNT2的所有客户的ID的客户信息
SELECT cust_name,cust_contact
FROM customers,orders,orderitems
WHERE customers.cust_id = orders.cust_id
AND orderitems.order_num= orders.order_num
AND prod_id = 'TNT2'
--子查询: 检索返回订购物品TNT2的所有客户的ID的客户信息
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 ='TNT2')
)
-- 不要联结不必要的表,联结的表越多,性能下降越厉害;
-- 通过为外键列有效地创建索引可以明显地改善这种性能下降;