数据库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數據庫引擎中是支持全文本搜索的
轉載于:https://blog.51cto.com/1095221645/1545905
總結
以上是生活随笔為你收集整理的数据库9:联结表 高级联结 组合查询 全文本搜索的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: windows批量创建用户
- 下一篇: category使用 objc_setA