数据库9:联结表 高级联结 组合查询 全文本搜索

第十五章联结表

Sql最强大的功能之一就是能在数据检索查询的执行中联结(join)表。联结是利用sql的select能执行的最重要的操作,能很好的理解联结及其语法是学习sql的一个极为重要的组成部分。

  外键:外键为某个表中的一列,它包含另一个表的主键值,定义了两个表之间的关系。

好处:供应商信息不重复,不浪费空间和时间,方便日后修改,一个表信息改动不影响另一个表的信息

联结是一种机制,使用特殊的语法,可以联结多个表返回一组输出,联结在运行时关联表中正确的行。

  创建联结

          SELECT vend_name , prod_name , prod_price

          FROM vendors , products

          WHERE vendors.vend_id =products . Vend_id

          ORDER BY vend_name , prod_name; ;

如果没有WHERE子句,表一中的每行将于表二中的每行配对,而不管他们逻辑是否可以配在一起。其配对的结果是 笛卡尔积。就是表一行数*表二行数

  内部联结

前面讲的联结称为等值联结,它基于两个表之间的相等测试。这种联结也称为内部联结。前其实这种联结可以使用稍微不同的语法来明确指定联结的类型。下面是语句与上面返回一样

   SELECT vend_name ,prod_name , prod_price

         FROM vendors

   INNERJOIN products ON vendors .vend_id = products . vend_id;

这里的两个表之间的关系是由FROM 子句组成的。以 INNER JION指定。使用这种语法时。联结子句的条件用特定的ON子句而不是WHERE子句给出。传递给ON的跟传递给WHERE的子句相同。

      首选使用INNER JOIN语法,这样不会忘记联结的条件,虽然WHERE子句定义联结比较简单。

  联结多个表

   SELECT prod_name ,vend_name ,prod_price , quantity

          FROM orderitems , products , vendors

   WHEREproducts . Vend_id =vendors.vend_id

   AND orderitems.prod_id =products.prod_id

   AND order_num =20005;

考虑到多个表联结时会耗费资源,所以尽量不要联结不必要的表。

第十六章 创建高级联结

  使用别名

     SELECTConcat(RTrim(vend_name) , ‘(‘ ,RTrim(vend_country) , ‘)‘)AS vend_title

    FROMvendors ORDER BYvend_name;

别名除了用于列名和计算字段外,sql还允许给表名起别名。一可以缩短sql语句,二允许在单条SELECT 语句中多次使用相同的表

   SELECT cust_name ,cust_contact

          FROM customers AS c ,orders AS o , orderitemsAS oi

        WHEREc.cust_id = o.cust_id ANDoi.order_num = o.order_num AND prod_id = ‘TN2‘

表的别名和列的别名不一样,表的别名不返回给客户端

   使用不同类型的联结

   前面为止我们使用的只是称为内部联结或等值联结的简单联结。现在来看其他3中联结。分别是自联结、自然联结和外部联结

  自联结

使用表别名的主要原因之一是能在单条SELECT语句中不止一次引用相同的表。举个例子:

如果发现某物品(id为abc)存在问题,因此想知道生产该物品的生产商生产的其他物品是否也存在问题。此程序要求首先找到生产id为abc的物品的生产商,然后找出这个生产商生产的其他的物品。下面一种解决方法:

   SELECT prod_id , prod_nameFROM products WHERE vend_id = (

    SELECT vend_id FROM products WHERE prod_id = ‘abc‘

    );

   上面使用的子查询,现在看使用联结的相同查询:

    SELECT p1.prod_id ,prod_name

          FROM productsAS p1 , productsAS p2

     WHEREp1.vend_id = p2.vend_id ANDp2.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 ordersON customers.cust_id =order_cust_id;

这条sql语句使用了关键字OUTER JOIN 来指定联结的类型(而不是WHERE指定)。但是与内部联结关联两个表中的行不同的是,外部联结还包括没有关联的行。

      使用OUTERJOIN 必须使用LEFT 或RIGHT关键字指定包括其所有含的表。

  使用带聚集函数的联结

聚集函数是用来汇总数据。它可以中单个表中汇总数据,也可以在联结中一起使用。

例子:检索所有客户及每个客户所下的订单数。。下面使用了COUNT()函数的代码完成。

SELECT customer.cust_name ,customer . cust_id , COUNT(order.order_num) AS num_ord

FROM customers

INNER JOIJN orders ONcustomers.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 ordersON customers.cust_id =order.cust_id

GROUP BYcustomers.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 WHEREprod_price <= 5

UNION

SELECT vend_id ,prod_id , prod_price FROM products WHEREvend_id IN (1001,1002)

OR语句也能实现上面的查询

SELECT vend_id ,prod_id , prod_price FROM products

WHEREprod_price <= 5 ORvend_id IN (1001,1002)

从上面这个简单的例子中,使用UNION可能比使用WHERE子句更为复杂。但对于更复杂的过滤条件,或者从多个表而不是单个表中检索数据的情形,使用UNION肯会使处理更简单

  UNION规则

正如所见,并是非常容易使用的,但在进行并时有几条规则需要注意

      1 UNION必须由两条或两条以上的SELECT语句组成,语句之间用关键字UNION分隔

      2 UNION中的每个查询必须包含相同的列、表达式或聚集函数(不过各列不需要以相同的次序列出)

      3 列数据类型必须兼容:类型不完全相同,但不想是DBMS可以隐含滴转换的类型。

  包含或取消重复的行

      如果SELECT语句中返回的行相同,UNION会自动的去除重复的行。这是他的默认行为,但是如果需要,可以改变它,可以使用UNION ALL 而不是UNION

SELECT vend_id ,prod_id , prod_price FROM products WHEREprod_price <= 5

UNION ALL

SELECT vend_id ,prod_id , prod_price FROM products WHEREvend_id IN (1001,1002)

  对组合查询结果排序

SELECT语句的输出用ORDER BY子句排序。在UNION组合查询时,只能使用一条ORDER BY子句,它必须出现在最后一条SELECT语句之后。

SELECT vend_id ,prod_id , prod_price FROM products WHEREprod_price <= 5

UNION ALL

SELECT vend_id ,prod_id , prod_price FROM products WHEREvend_id IN (1001,1002)

GROUP BY vend_id,prod_price;

第十八章全文本搜索

  理解全文本搜索

      并非所有的引擎都支持全文本搜索。最常使用的是MyISAM和InnoDB,前者支持全文本搜索,而后者不支持。如果你需要全文本搜索功能,应该记住这一点

      关键字LIKE,它利用通配操作匹配的文本(和部分文本)。使用LIKE,能够查找包含特殊值或部分值的行(不管这些值位于那些位置)

      基于文本的搜索作为正则表达式匹配列值的更进一步的介绍。使用正则表达式,可以编写查找所有行的非常复杂的匹配模式

      虽然这些搜索机制非常有用。但存在几个重要的限制:

          1性能——通配符和正则表达式匹配通常要求MYSQL尝试匹配表中所有的行(而且这些搜索极少使用表索引),因此,由于被搜索行数不断增加,这些搜索非常耗时

          2明确控制——使用通配符和正则表达式匹配,很难(而且并不总能)明确的控制匹配什么和不匹配什么

          3智能化的结果——虽然前两者都能提供了非常灵活的搜索,但它们都不能提供非常智能化的匹配结果。

      前面的很多限制都可以使用全文本搜索来解决。使用全文本搜索。Mysql创建指定列中各词的一个索引, 搜索可以针对这些词进行。

  使用全文本搜索

      启用全文本搜索

      一般在创建表时启用全文本搜索。CREATE TABLE语句接受FULLTEXT子句。它给出被索引列的一个逗号分隔的列表。

      CREATE TABLE productontes

      (

   note_idint NOT_NULL AUTO_INCREMENT,

   prod_id char(10) NOT_NULL,

   note_date datetimeNOT_NULL,

   note_text text NOT_NULL,

   PRIMARY KEY(note_id),

   FULLTEXT(note_text)

       )ENGINE=MyISAM;

      为了进行全文本搜索,mysql根据子句FULLTEXT(note_text)的指示对它进行索引。这里FUNLL_TEXT索引了单个列,如果需要可以索引多个列,多列之间用逗号分隔

      在定义之后mysql对自动维护该索引,在增加、更新和删除行时,索引随之自动更新。

      不要在导入数据时使用FUNLLTEXT,否则会耗费很多时间,应该先导入数据,再定义FULLTEXT这样有助于更快的导入数据

  进行全文本搜索

      在索引之后,使用两个函数Match()和Against()执行全文本搜索,其中Match()指定被搜索的列Against()指定要使用的搜索表达式。

          SELECT note_text FROMproductnotes WHERE Match(note_text) Against(‘rabbit‘);

      使用完整的Match()说明: 传递给Match()的值必须和与FULLTEXT()定义中的相同。如果指定了多个列,则必须列出它们(而且次序正确)

      除非使用BINARY方式,否则全文本搜索不区分大小写

      使用SELECT 语句同样可以检索出两行,但次序不同。

      全文本搜索返回一文本匹配的良好程度的数据。具有较高等级的行先返回。

  使用查询扩展

      查询扩展用来设法放宽所返回的全文本搜索结果的范围。想找出与搜索有关的其他行。不包含要搜索才字母。

          如SELECT note_text FROM productnotesWHERE Match(note_text) Against(‘anvils‘);

          返回一行数据

      使用查询扩展

          SELECT note_text FROMproductnotes

          WHERE Match(note_text) Against(‘anvils‘ WITHQUERY EXPANSION);

          返回7行

  布尔文本搜索

      Mysql支持全文本搜索的另一种形式,称为布尔方式。布尔方式可以提供以下细节:

          1要匹配的词

          2要排斥的词(如果该行包含这个词,则不返回该行,即使它已经包含指定的词也是如此)

          3排列提示(指定某些词比其他词重要,更重要的词的词等级更高)

          4表达式分组

          5另外一些内容

      即使没有FULLTEXT索引也可以使用  布尔方式不同迄今为止使用的全文本搜索语法的地方在于,即使没有定义FULLTEXT索引,也可以使用它,但这是一种非常缓慢的操作(其性能将随着数据量的增加而降低)

      例如:匹配包含heavy但不包含任意以rope开始的词的行,可以使用以下查询:

          SELECT note_text FROMproductnotes

          WHERE Match(note_text) Against(‘heavy -rope*‘ IN BOOLEAN MODE)

      全文本布尔操作符

          +包含,词必须存在

          -排除,词必须不出现

          > 包含,而且增加等级值

          < 包含,而且减少等级值

          () 吧词组成子表达式(允许这些子表达式作为一个组被包含)

          ~取消一个词的排序值

          *词尾的通配符

          "" 定义一个短语,(与单词不一样,它匹配整个短语以便包含或排除这个短语)

          SELECT note_text FROMproductnotes

          WHERE Match(note_text) Against(‘+hea +rop‘ IN BOOLEAN MODE)

          //包含hea 和rop的行

          SELECT note_text FROMproductnotes

          WHERE Match(note_text) Against(‘hea rop‘ IN BOOLEANMODE)

          //包含hea 和rop至少一个就行的行

          SELECT note_text FROMproductnotes

          WHEREMatch(note_text) Against(‘"hea rop"‘ IN BOOLEAN MODE)

          //包含hea rop这个短语而不是hea和rop的行

          SELECT note_text FROMproductnotes

          WHERE Match(note_text) Against(‘>hea <rop‘ INBOOLEAN MODE)

          //包含hea 和rop的行,增加前者的等级,降低后者的等级

          SELECT note_text FROMproductnotes

          WHERE Match(note_text) Against(‘+hea +(<rop)‘ IN BOOLEANMODE)

          //包含hea 和rop的行降低后者的等级

  全文本搜索使用说明:

      1在索引全文本数据时,短语被忽略且从索引中排除,短语定义为那些具有3个或3个以下字符的词,如果需要,这个数目可以更改

      2mysql内建一个非用词(stopword)列表,这些词在索引全文本数据时总是被忽略,如果需要,可以覆盖这个列表

      3许多词出现的频率高,搜索它们没有用处(返回太多的结果),因此mysql规定了一条50%的规则,如果一个词出现在50%以上的行中,则它将作为一个非用词忽略,50%规则不适用与IN BOOLEAN MODE

      4如果表中的行数少于3行,则全文本搜索不返回结果(因为每个词或者不出现,或者少于出现在50%的行中)

      5忽略词中的单引号,例如 don‘t 索引为 dont

      6不具有词分隔符(包含日语和汉语)的语言不能恰当地返回全文本搜索结果

      7如前所述,仅在MyISAM数据库引擎中是支持全文本搜索的

时间: 2024-08-02 22:55:33

数据库9:联结表 高级联结 组合查询 全文本搜索的相关文章

MySQL数据检索+查询+全文本搜索

[0]README 0.1)本文部分文字描述转自"MySQL 必知必会",旨在review"MySQL数据检索+查询+全文本搜索" 的基础知识: [1]使用子查询 1)查询定义:任何sql 语句都是查询.但此术语一般指 select语句:SQL 还允许创建子查询,即嵌套在其他查询中的查询: 2)利用子查询进行过滤(where子句,in子句) 2.1)可以把一条select语句返回的结果用于另一条select语句的where子句: 3)作为计算字段使用子查询 3.1)

数据库、数据表的基本操作及查询数据

数据库的基本操作 创建数据库 CREATE DATABASE database_name database_name为要创建的数据库的名称 删除数据库 DROP DATABASE database_name database_name为要删除的数据库的名称 数据库存储引擎 数据库存储引擎是数据库底层软件组成,数据库管理系统(DBMS)使用数据引擎进行创建.查询.更新和删除数据操作. MySQL的核心就是存储引擎. 存储引擎比较 |功能|MyISAM|Memory|InnoDB|Archive|

2015-10-19 SQL(新建数据库、创建表、注释、查询语句、新增、更新、删除、联合查询)

1.认识数据库并新建: 1)打开数据库,连接到服务器. 2)服务里类型不用管. 3)服务器名称:打个点“.”表示服务器在本地计算机,如果是托管在别人的服务器上,就输入服务器IP地址. 4)身份验证:如果是windows身份验证,就需要有管理员权限.一般托管在别人的服务器上,(包括正常情况下),都是用SQL身份验证,需要输入sa和密码(密码就是安装时让输入的密码). 2.  建立数据库: 在建立数据库名称时(各种名称时),都遵守一个命名规则: 1)用英文命名 2)每个单词的首字母大写(驼峰原则:首

2015.7.30 第十五课 sql(新建数据库、创建表、注释、查询语句、新增、更新、删除、联合查询)

1.认识数据库并新建: 1)打开数据库,连接到服务器. 2)服务里类型不用管. 3)服务器名称:打个点“.”表示服务器在本地计算机,如果是托管在别人的服务器上,就输入服务器IP地址. 4)身份验证:如果是windows身份验证,就需要有管理员权限.一般托管在别人的服务器上,(包括正常情况下),都是用SQL身份验证,需要输入sa和密码(密码就是安装时让输入的密码). 2.  建立数据库: 在建立数据库名称时(各种名称时),都遵守一个命名规则: 1)用英文命名 2)每个单词的首字母大写(驼峰原则:首

【知识库】-数据库_MySQL之高级数据查询:去重复、组合查询、连接查询、虚拟表

简书作者:seay 文章出处: 关系数据库SQL之高级数据查询:去重复.组合查询.连接查询.虚拟表 回顾:[知识库]-数据库_MySQL之基本数据查询:子查询.分组查询.模糊查询 Learn [已经过测试校验] 一.去重复(DISTINCT) 二.组合查询 三.UNION(并集) 四.连接查询 五.虚拟表 一.去重复(DISTINCT) DISTINCT:用于返回唯一不同的值,主要是用于某一字段 语法 SELECT DISTINCT <列名>|* FROM <表名> 示例 -- 查

sql两个表的组合查询以及yii下使用数据库查询

sql两个表的组合查询  使用 join on 例如:两个表查询: select u.username, t.title from user u join task t on u.id = t.id; 其中  user u 是用来把表名简化   join则是加入其他的表    on则是表示查询的条件   u.username 则是表示user表中的username字段 同样的道理  多表查询的原理也是一样的 这是sql语句: select * from user u join task t on

MySQL创建高级联结

SQL允许给表取别名,这样做的两个主要理由是: 缩短SQL语句: 允许在单条SELECT语句中多次使用同一个表: 与之前相对应的我们使用别名来表示一个表: 自联结 问题:假如知道某一厂商生产的一个产品 ID 为 DTNTR有问题,需要从数据库中查找出该厂商生产的其他所有产品. 下面的SELECT语句可以将该vend_id所生产的所有产品查找出来: 现在来看使用联结的相同查询: MySQL创建高级联结,布布扣,bubuko.com

《MySQL必知必会学习笔记》:高级联结

创建高级联结 上篇博文简单的介绍了下联结的使用,这篇博文就介绍下如何来创建高级联结. 使用表别名 在前面的学习中,我们知道如何给列取一个别名,现在回顾下,如下: select cust_name,upper(cust_name) as upper_name from customers; 或者是,用concat函数来对客户的姓名和电话进行组合为一个新的信息 ,将这个新的信息取一个别名,如下: 以上就是给列取别名,也可以给计算字段取别名.不仅如此,SQL还允许给表名取别名.这样做有两个主要理由,如

11.联结表---SQL

说明:使用交互式DBMS工具重要的是,要理解联结不是物理实体.换句话说,它在实际的数据库表中并不存在.DBMS会根据需要建立联结,它在查询执行期间一直存在. 一.等值语法:SELECT 字段 FROM 表1,表2 WHERE 表1.字段=表2.字段 SELECT vend_name, prod_name, prod_price FROM Vendors, Products WHERE Vendors.vend_id = Products.vend_id; 分析▼我们来看这段代码.SELECT语句