07-查询操作(DQL)-多表查询

Posted 奔跑的路上

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了07-查询操作(DQL)-多表查询相关的知识,希望对你有一定的参考价值。

一. 综述

   查询操作主要从两个方面来说:单表查询和多表查询。 多表查询包括:笛卡尔积、外键约束、内连接查询、外链接查询、自连接查询。

二 . 案例设计

  1.  设计产品表(product)。包括:主键id、产品名称(productName)、分类编号(dir_id)、零售价(salePrice)、供应商(supplier)、品牌(brand)、折扣(cutoff)、成本价(costPrice)。

      设计产品产品编号表( productdir)。 包括:主键id、编号名称( dirName)、父id( parent_id) 。

      设计产品库存表( productstock)。包括:主键id、产品id( product_id )、库存数量( storeNum)、上次进库时间(lastIncomeDate)、上次出库时间( lastOutcomeDate)、预警数量(warningNum)。

      

       

       

   对应的SQL语句:

 1 CREATE TABLE `product` (
 2   `id` bigint(11) NOT NULL AUTO_INCREMENT,
 3   `productName` varchar(50) DEFAULT NULL,
 4   `dir_id` bigint(11) DEFAULT NULL,
 5   `salePrice` double(10,2) DEFAULT NULL,
 6   `supplier` varchar(50) DEFAULT NULL,
 7   `brand` varchar(50) DEFAULT NULL,
 8   `cutoff` double(2,2) DEFAULT NULL,
 9   `costPrice` double(10,2) DEFAULT NULL,
10   PRIMARY KEY (`id`)
11 ) ENGINE=MyISAM AUTO_INCREMENT=21 DEFAULT CHARSET=utf8;
12 
13 -- ----------------------------
14 -- Records of product
15 -- ----------------------------
16 INSERT INTO `product` VALUES (\'1\', \'罗技M90\', \'3\', \'90.00\', \'罗技\', \'罗技\', \'0.50\', \'35.00\');
17 INSERT INTO `product` VALUES (\'2\', \'罗技M100\', \'3\', \'49.00\', \'罗技\', \'罗技\', \'0.90\', \'33.00\');
18 INSERT INTO `product` VALUES (\'3\', \'罗技M115\', \'3\', \'99.00\', \'罗技\', \'罗技\', \'0.60\', \'38.00\');
19 INSERT INTO `product` VALUES (\'4\', \'罗技M125\', \'3\', \'80.00\', \'罗技\', \'罗技\', \'0.90\', \'39.00\');
20 INSERT INTO `product` VALUES (\'5\', \'罗技木星轨迹球\', \'3\', \'182.00\', \'罗技\', \'罗技\', \'0.80\', \'80.00\');
21 INSERT INTO `product` VALUES (\'6\', \'罗技火星轨迹球\', \'3\', \'349.00\', \'罗技\', \'罗技\', \'0.87\', \'290.00\');
22 INSERT INTO `product` VALUES (\'7\', \'罗技G9X\', \'3\', \'680.00\', \'罗技\', \'罗技\', \'0.70\', \'470.00\');
23 INSERT INTO `product` VALUES (\'8\', \'罗技M215\', \'2\', \'89.00\', \'罗技\', \'罗技\', \'0.79\', \'30.00\');
24 INSERT INTO `product` VALUES (\'9\', \'罗技M305\', \'2\', \'119.00\', \'罗技\', \'罗技\', \'0.82\', \'48.00\');
25 INSERT INTO `product` VALUES (\'10\', \'罗技M310\', \'2\', \'135.00\', \'罗技\', \'罗技\', \'0.92\', \'69.80\');
26 INSERT INTO `product` VALUES (\'11\', \'罗技M505\', \'2\', \'148.00\', \'罗技\', \'罗技\', \'0.92\', \'72.00\');
27 INSERT INTO `product` VALUES (\'12\', \'罗技M555\', \'2\', \'275.00\', \'罗技\', \'罗技\', \'0.88\', \'140.00\');
28 INSERT INTO `product` VALUES (\'13\', \'罗技M905\', \'2\', \'458.00\', \'罗技\', \'罗技\', \'0.88\', \'270.00\');
29 INSERT INTO `product` VALUES (\'14\', \'罗技MX1100\', \'2\', \'551.00\', \'罗技\', \'罗技\', \'0.76\', \'300.00\');
30 INSERT INTO `product` VALUES (\'15\', \'罗技M950\', \'2\', \'678.00\', \'罗技\', \'罗技\', \'0.78\', \'320.00\');
31 INSERT INTO `product` VALUES (\'16\', \'罗技MX Air\', \'2\', \'1299.00\', \'罗技\', \'罗技\', \'0.72\', \'400.00\');
32 INSERT INTO `product` VALUES (\'17\', \'罗技G1\', \'4\', \'155.00\', \'罗技\', \'罗技\', \'0.80\', \'49.00\');
33 INSERT INTO `product` VALUES (\'18\', \'罗技G3\', \'4\', \'229.00\', \'罗技\', \'罗技\', \'0.77\', \'96.00\');
34 INSERT INTO `product` VALUES (\'19\', \'罗技G500\', \'4\', \'399.00\', \'罗技\', \'罗技\', \'0.88\', \'130.00\');
35 INSERT INTO `product` VALUES (\'20\', \'罗技G700\', \'4\', \'699.00\', \'罗技\', \'罗技\', \'0.79\', \'278.00\');
CREATE TABLE `productdir` (
  `id` bigint(11) NOT NULL auto_increment,
  `dirName` varchar(30) default NULL,
  `parent_id` bigint(11) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records 
-- ----------------------------
INSERT INTO `productdir` VALUES (\'1\', \'鼠标\', null);
INSERT INTO `productdir` VALUES (\'2\', \'无线鼠标\', \'1\');
INSERT INTO `productdir` VALUES (\'3\', \'有线鼠标\', \'1\');
INSERT INTO `productdir` VALUES (\'4\', \'游戏鼠标\', \'1\');

CREATE TABLE `productstock` (
  `id` bigint(11) NOT NULL auto_increment,
  `product_id` bigint(11) default NULL,
  `storeNum` int(10) default NULL,
  `lastIncomeDate` datetime default NULL,
  `lastOutcomeDate` datetime default NULL,
  `warningNum` int(10) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records 
-- ----------------------------
INSERT INTO `productstock` VALUES (\'1\', \'1\', \'182\', \'2015-03-12 20:33:00\', \'2015-03-12 20:33:04\', \'20\');
INSERT INTO `productstock` VALUES (\'2\', \'2\', \'27\', \'2015-03-02 20:33:28\', \'2015-03-09 20:33:40\', \'20\');
INSERT INTO `productstock` VALUES (\'3\', \'3\', \'89\', \'2015-02-28 20:34:13\', \'2015-03-12 20:34:19\', \'20\');
INSERT INTO `productstock` VALUES (\'4\', \'5\', \'19\', \'2015-03-01 20:34:43\', \'2015-03-12 20:34:48\', \'20\');
INSERT INTO `productstock` VALUES (\'5\', \'6\', \'3\', \'2015-02-01 20:35:12\', \'2015-03-02 20:35:16\', \'5\');
INSERT INTO `productstock` VALUES (\'6\', \'7\', \'2\', \'2015-02-02 20:35:59\', \'2015-02-27 20:36:05\', \'3\');
INSERT INTO `productstock` VALUES (\'7\', \'8\', \'120\', \'2015-03-12 20:36:31\', \'2015-03-12 20:36:33\', \'20\');
INSERT INTO `productstock` VALUES (\'8\', \'9\', \'58\', \'2015-03-02 20:36:50\', \'2015-03-12 20:36:53\', \'20\');
INSERT INTO `productstock` VALUES (\'9\', \'11\', \'28\', \'2015-03-02 20:37:12\', \'2015-03-12 20:37:15\', \'20\');
INSERT INTO `productstock` VALUES (\'10\', \'12\', \'8\', \'2015-03-02 20:37:35\', \'2015-03-09 20:37:38\', \'5\');
INSERT INTO `productstock` VALUES (\'11\', \'13\', \'3\', \'2015-03-02 20:37:58\', \'2015-03-12 20:38:01\', \'5\');
INSERT INTO `productstock` VALUES (\'12\', \'14\', \'6\', \'2015-03-02 20:38:20\', \'2015-03-07 20:38:23\', \'5\');
INSERT INTO `productstock` VALUES (\'13\', \'15\', \'2\', \'2015-02-02 20:38:38\', \'2015-02-24 20:38:44\', \'5\');
INSERT INTO `productstock` VALUES (\'14\', \'16\', \'3\', \'2015-02-02 20:39:05\', \'2015-02-06 20:39:09\', \'3\');
INSERT INTO `productstock` VALUES (\'15\', \'17\', \'49\', \'2015-03-02 20:39:36\', \'2015-03-12 20:39:40\', \'20\');
INSERT INTO `productstock` VALUES (\'16\', \'18\', \'14\', \'2015-03-02 20:39:57\', \'2015-03-09 20:40:01\', \'10\');
INSERT INTO `productstock` VALUES (\'17\', \'20\', \'7\', \'2015-03-02 20:40:22\', \'2015-03-03 20:40:25\', \'5\');

   

     

     

三. 多表查询

1. 笛卡尔积

  多表查询会产生笛卡尔积。 假设集合A={a,b},集合B={0,1,2},则两个集合的笛卡尔积为{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}。实际运行环境下,应避免使用全笛卡尔集。

      解决笛卡尔积最有效的方法:等值连接。

       

-- 需求:查询所有的货品信息+对应的货品分类信息
SELECT productName,dirName FROM product,productdir WHERE dir_id = productdir.id

2. 外键约束

主键约束(PRIMARY KEY): 约束在当前表中,指定列的值非空且唯一.

外键约束(FOREIGN KEY): A表中的外键列. A表中的外键列的值必须参照于B表中的某一列(B表主键).

注意:在mysql中,InnoDB支持事务和外键.修改表的存储引擎为InnDB。

格式:ALTER TABLE 表名 ENGINE=\'InnoDB\'。

        

       主表:数据可以独立存在,就是被参考的表。 productdir

       从表:表中的数据,必须参照于主表的数据。product

       注意:在删除表的时候,先删除从表,再删除主表。

      

3. 多表查询详解

    多表查询包括三类:内连接查询(隐式内连接和显示内连接)、外连接查询 (左外链接、右外链接、全链接 )、自连接查询。

     

     (1). 内连接

   隐式内连接:查询出来的结果是多表交叉共有的。

     格式:

          

      显式内连接:

       格式:

           

       注意:在做等值连接的时候,若A表中的和B表中的列相同,可以缩写为:

       

       

需求:查询所有商品的名称和分类名称:
隐式内连接: 
SELECT p.productName,pd.dirName FROM product p,productdir pd WHERE p.dir_id = pd.id
显示内连接: 
SELECT p.productName,pd.dirName FROM product p INNER JOIN productdir pd ON p.dir_id = pd.id
显示内连接:
 SELECT p.productName,pd.dirName FROM product p JOIN productdir pd ON p.dir_id = pd.id


需求: 查询零售价大于200的无线鼠标
SELECT * FROM product p,productdir pd WHERE p.dir_id = pd.id AND p.salePrice >200 And 
pd.dirName =\'无线鼠标\'

SELECT * FROM product p JOIN productdir pd on p.dir_id = pd.id WHERE p.salePrice >200 And 
pd.dirName =\'无线鼠标\'

需求: 查询每个货品对应的分类以及对应的库存
SELECT p.productName,pd.dirName,ps.storeNum 
FROM product p,productdir pd,productstock ps 
WHERE  p.dir_id = pd.id AND p.id = ps.product_id

SELECT p.productName,pd.dirName,ps.storeNum 
FROM product p 
JOIN productdir pd on  p.dir_id = pd.id
JOIN productstock ps on p.id = ps.product_id

需求: 如果库存货品都销售完成,按照利润从高到低查询货品名称,零售价,货品分类(三张表).
select *, (p.salePrice - p.costPrice) * ps.storeNum lirun
FROM product p,productdir pd,productstock ps 
WHERE  p.dir_id = pd.id AND p.id = ps.product_id
ORDER BY lirun DESC

select *, (p.salePrice - p.costPrice) * ps.storeNum lirun
FROM product p 
JOIN productdir pd on  p.dir_id = pd.id
JOIN productstock ps on p.id = ps.product_id
ORDER BY lirun DESC

   (2). 外连接查询

      左外连接:查询出JOIN左边表的全部数据,JOIN右边的表不匹配的数据用NULL来填充。

     右外连接:查询出JOIN右边表的全部数据,JOIN左边的表不匹配的数据用NULL来填充。

     eg: A LEFT JOIN B  等价于  B RIGHT JOIN A

      

      

-- 外链接
# 查询所有商品的名称和分类名称
左连接:
SELECT * FROM product p LEFT JOIN productdir pd ON p.dir_id = pd.id
-- 等价于
SELECT * FROM  productdir pd RIGHT JOIN product p ON p.dir_id = pd.id
右连接:
SELECT * FROM product p RIGHT JOIN productdir pd ON p.dir_id = pd.id

       (3). 自连接查询:把一张表看成两张表来做查询

       

 

以上是关于07-查询操作(DQL)-多表查询的主要内容,如果未能解决你的问题,请参考以下文章

06-查询操作(DQL)

MySQL数据操作DQL:多表查询2

DQL:数据查询复杂的(多表)

九:SQL之DQL数据查询语言多表操作

数据库1mysql安装,DDL/DML,DQL,外键约束,多表/子查询,事务,登陆案例,预编译,连接池,jdbcTemplate方法,redis安装,操作,持久化,Jedis,总结

08_MySQL DQL(SQL99标准)_多表连接查询中的内连接