考虑到多个表联结时会耗费资源,所以尽量不要联结不必要的表。
第十六章 创建高级联结
使用别名
SELECT Concat(RTrim(vend_name) , '(' , RTrim(vend_country) , ')') AS vend_title
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 oi.order_num = o.order_num AND prod_id = 'TN2'
表的别名和列的别名不一样,表的别名不返回给客户端
使用不同类型的联结
前面为止我们使用的只是称为内部联结或等值联结的简单联结。现在来看其他3中联结。分别是自联结、自然联结和外部联结
自联结
使用表别名的主要原因之一是能在单条SELECT语句中不止一次引用相同的表。举个例子:
如果发现某物品(id为abc)存在问题,因此想知道生产该物品的生产商生产的其他物品是否也存在问题。此程序要求首先找到生产id为abc的物品的生产商,然后找出这个生产商生产的其他的物品。下面一种解决方法:
SELECT prod_id , prod_name FROM products WHERE vend_id = (
SELECT vend_id FROM products WHERE prod_id = 'abc'
);
上面使用的子查询,现在看使用联结的相同查询:
SELECT p1.prod_id , prod_name
FROM products AS p1 , products AS p2
WHERE p1.vend_id = p2.vend_id AND p2.prod_id = 'abc';
此联结查询需要的两个表实际上同一个表,
用自联结不用子查询 子联结通常作为外部语句用来代替从相同表中检索数据时使用的子查询语句,虽然结果一样,但是处理联结远不处理子查询要快的多。
自然联结
SELECT * 改为 SELECT 表名1.列名1 , 表名2.列名3 这样可以去除无用的列。执行效率更快
外部联结
许多联结将一个表中的行与另一个表中的行相关联。但有时候会需要包含没有关联行的那些行。
例如完成需要使用联结完成以下任务:
1 对每个用户下了多少订单进行计数,包括那些至今尚未下订单的客户
2 列出所有产品以及订购数量,包括那些没有人订购的产品
3 计数平均销售规模,包括那些至今未下订单的客户
上述例子中,联结包含了那些在相关表中没有关联的行,这种联结类型的联结称为外部联结。
下面是SELECT 语句给出一个简单的内部联结。它检索出了所有客户以及订单:
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 = order_cust_id;
这条sql语句使用了关键字OUTER JOIN 来指定联结的类型(而不是WHERE指定)。但是与内部联结关联两个表中的行不同的是,外部联结还包括没有关联的行。
使用OUTER JOIN 必须使用LEFT 或 RIGHT关键字指定包括其所有含的表。
使用带聚集函数的联结
聚集函数是用来汇总数据。它可以中单个表中汇总数据,也可以在联结中一起使用。
例子:检索所有客户及每个客户所下的订单数。。下面使用了COUNT()函数的代码完成。
SELECT customer.cust_name , customer . cust_id , COUNT(order.order_num) AS num_ord
FROM customers
INNER JOIJN orders ON customers.cust_id = orders.cust_id
GROUP BY customers.cust;
GROUP BY 子句按客户分组数据。因此,函数调用COUNT (orders.order_num)对每个客户的订单计数,将他作为num_ord返回
聚集函数也可以方便地与其他联结一起使用
SELECT customers.cust_name , customers.cust_id , COUNT(order.order_num) AS num_ord
FROM customers
LEFT OUTER JOIN orders ON customers.cust_id = order.cust_id
GROUP BY customers.cust_id;
使用联结和联结条件
1 注意所使用的联结类型,一般我们使用内部联结,但使用外部联结也是有效的。
2 保证使用正确的联结条件,否则将返回不正确的数据;
3 应该始终提供联结条件,否则会得出笛卡尔积
4 在一个联结中可以包含多个表,甚至对于每个联结可以采用不同的联结类型。虽然这样做是合法的,一般也很有用,但应该在测试它们之前,分别测试每个联结。这将使故障排除更为简单。
第十七章 组合查询
前面的都是从一个或多个表中返回数据的单条SELECT 语句。MYSQL也允许执行多个查询(多条SELECT语句),并将结果作为单条查询结果集返回。这些组合查询通常称为 并 union 或复合查询
有两种情况需要使用组合查询
1 在单个查询中从不同的表返回累世结构的数据
2 对单个表执行多个查询,按单个查询返回数据
组合查询和多个WHERE条件多数情况下,组合相同表的两个查询完成的工作与具有多个WHERE子句完成的工作相同,换句话说,任何具有多个WHERE子句的SELECT语句都可以作为一个组合查询给出。
创建组合查询
可用UNION操作符来组合数条SQL查询。给出多条SELECT语句,将它们的结合组合成单个结果返回
使用UNION
使用很简单,在多条SELECT语句之间放上关键词UNION。
例如:需要价格不大于5元,但是又要包含供应商1002和1001的所有产品,(不考虑价格)
SELECT vend_id ,prod_id , prod_price FROM products WHERE prod_price <= 5
UNION
SELECT vend_id ,prod_id , prod_price FROM products WHERE vend_id IN (1001,1002)