SQL必知必會筆記十三(建立高階聯結)

2021-10-05 14:28:49 字數 4967 閱讀 9717

另外一些聯結(包括它們的含義和使用方法),介紹如何使用表別名,如何對被聯結的表使用聚集函式。

例如:給列起別名

select 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 = 'rgan01';

可以看到,from子句中的三個表全都有別名。customers as c使用c作為customers的別名,如此等等。這樣,就可以使用省略的c而不用全名customers。在這個例子中,表別名只用於where子句。其實它不僅能用於where子句,還可以用於select的列表、order by子句以及其他語句部分。

注意:oracle中沒有as

oracle不支援as關鍵字。要在oracle中使用別名,可以不用as,簡單地指定列名即可(因此,應該是customers c,而不是customers as c)。

需要注意,表別名只在查詢執行中使用。與列別名不一樣,表別名不返回到客戶端。

迄今為止,我們使用的只是內聯結或等值聯結的簡單聯結。現在來看三種其他聯結:自聯結(self-join)、自然聯結(natural join)和外聯結(outer join)。

自聯結

使用表別名的乙個主要原因是能在一條select語句中不只一次引用相同的表。

例如:要給與jim jones同一公司的所有顧客傳送一封信件。這個查詢要求首先找出jim jones工作的公司,然後找出在該公司工作的顧客。

使用子查詢

select cust_id, cust_name, cust_contact from customers where cust_name = (select cust_name from customers where cust_contact = 'jim jones');

使用聯結

select c1.cust_id, c1.cust_name, c1.cust_contact from customers as c1, customers as c2 where c1.cust_name = c2.cust_name and c2.cust_contact = 'jim jones';

oracle使用者應該記住去掉as。

此查詢中需要的兩個表實際上是相同的表,因此customers表在from子句**現了兩次。雖然這是完全合法的,但對customers的引用具有歧義性,因為dbms不知道你引用的是哪個customers表。

解決此問題,需要使用表別名。customers第一次出現用了別名c1,第二次出現用了別名c2。現在可以將這些別名用作表名。例如,select語句使用c1字首明確給出所需列的全名。如果不這樣,dbms將返回錯誤,因為名為cust_id、cust_name、cust_contact的列各有兩個。dbms不知道想要的是哪一列(即使它們其實是同一列)。where首先聯結兩個表,然後按第二個表中的cust_contact過濾資料,返回所需的資料。

自聯結通常作為外部語句,用來替代從相同表中檢索資料的使用子查詢語句。雖然最終的結果是相同的,但許多dbms處理聯結遠比處理子查詢快得多。

自然聯結

無論何時對錶進行聯結,應該至少有一列不只出現在乙個表中(被聯結的列)。標準的聯結(前一課中介紹的內聯結)返回所有資料,相同的列甚至多次出現。自然聯結排除多次出現,使每一列只返回一次。

怎樣完成這項工作呢?答案是,系統不完成這項工作,由你自己完成它。自然聯結要求你只能選擇那些唯一的列,一般通過對乙個表使用萬用字元(select *),而對其他表的列使用明確的子集來完成。

例如:select c.*, o.order_num, o.order_date, oi.prod_id, oi.quantity, oi.item_price 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 = 'rgan01';

oracle使用者應該記住去掉as。

萬用字元只對第乙個表使用。所有其他列明確列出,所以沒有重複的列被檢索出來。

事實上,我們迄今為止建立的每個內聯結都是自然聯結,很可能永遠都不會用到不是自然聯結的內聯結。

外聯結

許多聯結將乙個表中的行與另乙個表中的行相關聯,但有時候需要包含沒有關聯行的那些行。

例如:• 對每個顧客下的訂單進行計數,包括那些至今尚未下訂單的顧客;

• 列出所有產品以及訂購數量,包括沒有人訂購的產品;

• 計算平均銷售規模,包括那些至今尚未下訂單的顧客。

內聯結:檢索所有顧客和訂單

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 = orders.cust_id;

在上述例子中,聯結包含了那些在相關表中沒有關聯行的行。這種聯結稱為外聯結。

這條select語句使用了關鍵字outer join來指定聯結型別(而不是在where子句中指定)。但是,與內聯結關聯兩個表中的行不同的是,外聯結還包括沒有關聯行的行。在使用outer join語法時,必須使用right或left關鍵字指定包括其所有行的表(right指出的是outer join右邊的表,而left指出的是outer join左邊的表)。上面的例子使用left outer join從from子句左邊的表(customers表)中選擇所有行。為了從右邊的表中選擇所有行,需要使用right outer join。

例如:select customers.cust_id, orders.order_num from customers right outer join orders on orders.cust_id = customers.cust_id;

注意:語法差別

需要注意,用來建立外聯結的語法在不同的sql實現中可能稍有不同。下面段落中描述的各種語法形式覆蓋了大多數實現,在繼續學習之前請參閱你使用的dbms文件,以確定其語法。

注意:sqlite外聯結

sqlite支援left outer join,但不支援right outer join。幸好,如果你確實需要在sqlite中使用right outer join,有一種更簡單的辦法,這將在下面的提示中介紹。

要記住,總是有兩種基本的外聯結形式:左外聯結和右外聯結。它們之間的唯一差別是所關聯的表的順序。換句話說,調整from或where子句中表的順序,左外聯結可以轉換為右外聯結。因此,這兩種外聯結可以互換使用,哪個方便就用哪個。

還存在另一種外聯結,就是全外聯結(full outer join),它檢索兩個表中的所有行並關聯那些可以關聯的行。與左外聯結或右外聯結包含乙個表的不關聯的行不同,全外聯結包含兩個表的不關聯的行。

例如:select customers.cust_id, orders.order_num from orders full outer join customers on orders.cust_id = customers.cust_id;

注意:full outer join的支援

access、mariadb、mysql、open office base和sqlite不支援full outer join語法。

聚集函式用來彙總資料。雖然至今為止我們舉的聚集函式的例子都只是從乙個表中彙總資料,但這些函式也可以與聯結一起使用。

例如:檢索所有顧客及每個顧客所下的訂單數

select customers.cust_id, count(orders.order_num) as num_ord from customers inner join orders on customers.cust_id = orders.cust_id group by customers.cust_id;

這條select語句使用inner join將customers和orders表互相關聯。group by子句按顧客分組資料,因此,函式呼叫count(orders.order_num)對每個顧客的訂單計數,將它作為num_ord返回。

聚集函式也可以方便地與其他聯結一起使用。

例如:使用左外部聯結來包含所有顧客,甚至包含那些沒有任何訂單的顧客。

select customers.cust_id, count(orders.order_num) as num_ord from customers left outer join orders on customers.cust_id = orders.cust_id group by customers.cust_id;

再次提醒oracle使用者,請記住刪除as。

聯結及其使用的要點。

• 注意所使用的聯結型別。一般我們使用內聯結,但使用外聯結也有效。

• 關於確切的聯結語法,應該檢視具體的文件,看相應的dbms支援何種語法(大多數dbms使用這兩課中描述的某種語法)。

• 保證使用正確的聯結條件(不管採用哪種語法),否則會返回不正確的資料。

• 應該總是提供聯結條件,否則會得出笛卡兒積。

• 在乙個聯結中可以包含多個表,甚至可以對每個聯結採用不同的聯結型別。雖然這樣做是合法的,一般也很有用,但應該在一起測試它們前分別測試每個聯結。這會使故障排除更為簡單。

SQL必知必會 筆記 第十三章 建立高階聯結

別名除了用於列名和計算欄位外,sql還允許給表明起別名。這樣做有兩個主要理由 1 縮短sql語句 2 允許在單條select語句中多次使用相同的表。select cust name,cust contact from customers as c,orders as o,orderitems as ...

《sql必知必會》筆記

資料庫 儲存有組織的資料的容器 通常是乙個檔案或一組檔案 注意誤用混淆 資料庫軟體被稱為dbms,資料庫是通過dbms建立和操縱的容器 模式 關於資料庫和表的布局及特性的資訊。主鍵 一列或一組列,其值能夠唯一標識表中的每一行。多條sql語句必須以 分隔。sql語句不區分大小寫,select和sele...

SQL 必知必會 筆記 20 高階SQL特性

約束 constraint 就是管理如何插入或處理資料庫資料的規則。dbms通過在資料庫表上施加約束來實施引用完整性。1.1 主鍵 主鍵是一種特殊的約束,用來保證一列 或一組列 中的值是唯一的,而且永不改動。列應用於主鍵的條件 我們可以在建立列的時候這樣定義主鍵 1 create table ven...