[WITH with_queries] SELECT select_list FROM table_expression [sort_specification]
一、select_list
a、「*」 :遍歷全部行和用戶定義的全部列從表中。select_list也可使用可用列的子集或列的計算,如:sql
select a, b+c from table1.
b、使用select命令忽略table_expression,將其當作計算器,如:select 3*4;
c、select_list中返回不一樣的結果,你能夠調用一個函數,如:select random();數據庫
二、table_expression
table_expression包含from從句,後面可跟where,group by,having從句,簡單的table_expression引用磁盤上的表,但複雜的table_expression能夠以不一樣的方式修改or結合基表。
可選where,group by,having從句指定逐次轉換管道執行在from子句派生表中。全部的轉換產生一個虛表,提供經過select_list 計算查詢輸出的行
a、from 從句
從給定的一個逗號分隔的表引用列表派生一個or多個其餘表,語法:
from table_reference [, table_reference [, …]]
table_reference能夠是一個表的名稱、派生表如子查詢、錶鏈接or這些複雜的組合。若是超過一個table_reference在from從句中列出,它們交叉鏈接造成中間虛表,而後經過where,group by,having從句轉換,造成最後的整個表的表達式。
錶鏈接
一個錶鏈接是來自其餘2個表(實表or派生表)根據特定鏈接類型的規則。
cross join
T1 cross join T2
從T1和T2中行進行每個可能的組合,如笛卡爾積。T1中有n行,T2中有m行,那麼交叉鏈接後,鏈接表有n*m行。
From T1 cross join T2 等效於 from T1, T2
也等效於:from T1 inner join T2 on true
限制鏈接
T1 {[inner]|{left|right|full}[outer]} join T2 on boolean_expression
T1 {[inner]|{left|right|full}[outer]} join T2 using(join column list)
T1 natural {[inner]|{left|right|full}[outer]} join T2
inner 和 outer 在全部鏈接中是可選的,默認爲inner;left,right,full屬於outer。
鏈接條件經過on 或 using從句or 經過關鍵字natural指定,鏈接條件決定了哪些行從2個源表匹配,詳細以下:
on從句最廣泛的一個鏈接條件:相似於where從句中的布爾表達式,若on從句爲true時,T1和T2匹配一對行。
using是一個速記符號:它以逗號分隔列名稱的列表,鏈接表必須有相同的列,造成一個鏈接條件所指定的每個列是相等。因此,using(a,b,c) 等效於 on(t1.a=t2.a and t1.b=t2.b and t1.c=t2.c)
natural是using的一個速記:使用using列表包含在輸入表中全部列的名稱,如沒有共同列,natural的行爲相似於交叉鏈接
inner join
在T1中每行R1,在T2中的每一行知足鏈接條件R1的行
left outer join
首先,執行inner join,而後,爲T1中不知足鏈接條件T2中任何行,鏈接行在T2中的列使用null值被添加,因此,鏈接表中至少有1行對應T1中的行。
right outer join
首先,執行inner join,而後,爲T2中不知足鏈接條件T1中任何行,鏈接行在T1中的列使用null值被添加,因此,鏈接表中至少有1行對應T2中的行。
full outer join
首先,執行inner join,而後, 爲T1中不知足鏈接條件T2中任何行,鏈接行在T2中的列使用null值被添加; 爲T2中不知足鏈接條件T1中任何行,鏈接行在T1中的列使用null值被添加。
t1表
num | name
-----+------
1 | a
2 | b
3 | c
(3 rows)
t2表
num | value
-----+-------
1 | xxx
3 | yyy
5 | zzz
(3 rows)
select * from t1 cross join t2;
select * from t1 inner join t2 on t1.num=t2.num;
select * from t1 inner join t2 using(num);
select * from t1 natural inner join t2;
select * from t1 left join t2 on t1.num=t2.num;
select * from t1 left join t2 using(num);
select * from t1 right join t2 on t1.num=t2.num;
select * from t1 right join t2 using(num);
select * from t1 full join t2 on t1.num=t2.num;
select * from t1 full join t2 using(num);
on從句也可以包含條件,但涉及直接錶鏈接,可能對一些查詢是有用:
select * from t1 left join t2 on t1.num=t2.num and t2.value='xxx';
注意:添加where從句將獲得不一樣的結果
select * from t1 left join t2 on t1.num=t2.num where t2.value='xxx';
由於在錶鏈接前的on從句已經被處理,而錶鏈接以後where從句被處理。
表和列的別名
能夠給表取一個臨時的名字,在查詢的其他部分引用,建立表的別名:
from table_reference as alias;
或
from table_reference alias;
一般,對錶名稱較長設置別名,可保持join從句可讀性
設置別名是當前查詢引用表的新名稱,在該查詢中不容許再使用原名稱
當join從句輸出結果使用別名,該別名隱藏了join從句內的原名稱
子查詢
指定一個派生表必須包括在括號中,必須指定表的別名,如:
from(select * from table1) as alias_name
當子查詢中涉及分組or彙集時,它不能下降到一個普通的錶鏈接
子查詢也能表示值列表
from (values('anne', 'smith'), ('bob','jone')) as names(first, last);
爲值列表的列指定別名也是可選的
表函數
產生行集的函數,由基本數據類型和組合數據類型組成。在查詢的from從句中,它們使用像一張表,視圖or子查詢。經過表函數返回的列能夠包含在select、join或where從句中以相同的方式做爲一個表,視圖or子查詢的列。
若是一個表函數返回一個基本數據類型,單結果列名匹配函數名,若函數返回複合類型,這些列的結果獲得一個該類型個體屬性。
b、where從句
where search_condition
search_condition返回boolean類型的值
在from從句處理完成後,從派生虛表中的每一行檢查search_condition,如檢查結果爲true,那麼該行被保持在輸出表中,不然(false/null)它將被丟棄。search_condition一般引用from從句中生成表中的至少一列,這不是必需,但不然,where從句沒有意義。
c、group by從句和having 從句
經過where從句過濾後,可能從派生的輸入表進行分組,使用group by從句,使用having從句消除組行。
select select_list from … [where …]
group by grouping_column_reference [, grouping_column_reference]...
將表中全部列中有相同值的列組合在一塊兒,消除冗餘的輸出or彙集計算。如:
表test1
x | y
---+---
a | 3
c | 2
b | 5
a | 1
(4 rows)
select x from test1 group by x;
這裏不能執行:select * from test1 group by x ,由於表中y列沒有單一的值與每個組相關,分組的列能夠引用select_list中的列由於它們在每一組中有單一值。
一般,若一個表被分組,沒有列在group by從句中的列不能被引用除了在聚合表達式中的列,如:select x, sum(y) from test1 group by x;
在嚴格的sql中,group by從句後列僅僅指源表中的列,但pg擴展,容許group by從句後的列是select_list中的列,分組表達式取代簡單列名也被支持。
若一張表已經使用group by進行分組,但只對一些組感興趣,可使用having從句過濾,相似與where從句,但只從分組的結果中過濾。語法:
select select_list from … [where …] group by …
having boolean_expression
boolean_expression能夠引用分組表達式和未分組的表達式(在一個聚合函數中的)
eg:
select x, sum(y) from test1 group by x having sum(y) > 3;
select x, sum(y) from test1 group by x having x < 'c';express
三、select lists
table_expression能夠經過組合表、視圖、分組等構建一箇中間虛表,該表最終由select_list處理,select_list來肯定中間表中的哪些列被輸出。
select_list items
最簡單的一種select_list是*,輸出由table_expression產生的全部列,不然,select_list是一個逗號分隔的值表達式or列的名字,列的名字能夠是表中真實列名字or別名。如有多於1張表有相同的列名,那麼必須給定其表的名稱,如:
Select tb1.a, tb2.a from …
若是在select_list增長任意的值表達式,那麼再返回表中增長一個新的虛擬列,值表達式對返回結果的每一行求值一次。服務器
column labels
select_list中的項能夠爲後續處理指定一個名稱,該名稱可用於如order by從句or客戶端的應用程序,如:
select a as value, b+c as sum from …
若沒有使用as指定列名,系統默認引用列名。函數調用,則使用函數名。複雜表達式,系統將生成一個通用的名稱。as爲可選,爲避免列名與pg中的關鍵字衝突,可使用雙引號,如:
Select a value, b+c as sum from … //value 爲pg中關鍵字
Select a 「value」, b+c as sum from …dom
distinct
select_list處理後,結果表能夠經過distinct來消除重複行,如:
select distinct select_list from …
用all取代distinct可保持全部行的默認行爲。若是2行中至少一列值不一樣,則2行認爲是不一樣的,null值在比較是相同的。另外,一個任意表達能夠肯定哪些行是不一樣的,語法:
Select distinct on (expression [, expression …]) select_list …
expression:評估全部行的任意值表達式,一個行集的全部表達式相等被視爲重複,只有行集中的第一個保留到輸出中。注意,行集的第一行是不可預知的,除非足夠列的查詢是排序,保證惟一的行排序在distinct處理前(distinct處理髮生在order by以後)
distinct on從句不是sql標準,有時被認爲很差的風格,由於處理結果的不肯定性,較好的作法:在from從句中使用group by和子查詢。函數
四、combining queries
2個查詢結果可使用union、intersection、difference操做符進行結合,語法:
query1 union [all] query2
query1 intersect [all] query2
query1 except [all] query2
set operations能夠被嵌套or組成鏈,如:
query1 union query2 union query3
union:添加query2的結果到query1中,雖然沒有保證行真實返回的順序。從它的結果中消除了重複行,相似於distinct;若使用union all不會消除重複行。
intersect:包含query1和query2中的全部行,重複行會消除除非all使用
except:返回在query1中不在query2中的全部行,重複行會消除除非all使用。
爲了計算2個查詢結果的union、intersection、difference,這2個query必須兼容,即他們返回相同的列數和相應的列具備兼容的數據類型。優化
五、Sorting Rows
通過查詢產生的輸出列表(在select list處理以後)能夠排序,如不指定行的排序,將返回一個不肯定的行順序,實際的順序依賴於掃描和鏈接計劃類型以及磁盤上的順序,但這個是不能依靠,只有明確指定排序才能返回一個特定的輸出順序。
order by從句指定排序:
select select_list from table_expression
order by sort_expression [ASC|DESC] [NULLS {FIRST|LAST}]
[, sort_expression2 [ASC|DESC] [NULLS {FIRST|LAST}] …]
sort_expression(s)能夠是select_list中任何有效的表達式:
select a,b from table1 order by a+b, c;
當指定排序表達式多個時,後面的排序表達式行排序是根據其前面的排序表達式的值進行比較。每一個表達式後面可跟ASC 或DESC關鍵字來指定行的順序是升序or降序,默認爲ASC。
NULLS FIRST 或NULLS LAST 是用來肯定nulls出如今 non-nulls以前或以後。默認null值排序大於任何non-null值,所以, NULLS FIRST是DESC的默認方式。
注意,排序選項是獨立的排序列,order by x,y DESC 等於 order by x ASC,y DESC
一個 sort_expression能夠是列標籤名 or 輸出列數,如根據輸出的第一列排序:
select a+b as sum, c from table1 order by sum;
select a, max(b) from table1 group by a order by 1;
注意,輸出列是單獨的列,以下面錯誤方式:
select a+b as sum, c from table1 order by sum + c;
這個限制減小了混亂,若是排序項名稱既匹配輸出列名字或表中列的名字時仍然存在混亂。
六、limit and offset
limit and offset容許你檢索一部分的行集,語法:
select select_list from table_expression
[order by …]
[limit {number|ALL}] [offset number]
若是指定limit count,不會有更多的行返回(但可能少於count,若是查詢自己行小於count)。Limit ALL等同於與忽略limit從句。
offset跳過多少行開始檢索返回行。Offset 0 至關於忽略offset從句。
當使用Limit時,使用order by 從句約束結果行集到一個惟一的序列很是重要。不然,你獲得一個不可預知的子集,你可能會問第十行至第二十行,但第十行至第二十行是什麼樣的順序?此順序未知,除非你明確指定order by
查詢優化以使用limit到帳戶當生成查詢計劃時,因此你頗有可能根據的給的limit 和 offset獲取不一樣的查詢計劃。所以,使用limit/offset值來選擇查詢結果的不一樣子集。
因爲offset從句是在服務器端計算,所以一個大的offset多是低效的。
七、values lists
values提供一個生成常量表的方式,它可使用在一個沒有真實建立和操做磁盤上表的查詢上,語法:
values (expression [, ...]) [, …]
每一個括號內的列表生成表裏的一行,列表必須有相同的元素數量(至關於表相同數量列)而且,每一個列表中相應的元素具備兼容的數據類型。結果列的實際類型由相同規則決定經過union,如:
VALUES (1, 'one'), (2, 'two'), (3, 'three');
等效於
SELECT 1 AS column1, 'one' AS column2
UNION ALL
SELECT 2, 'two' UNION ALL SELECT 3, 'three';
默認,pg指定column1,column2,等爲值表的列。這個column name不是sql標準而且不一樣的數據庫系統可能不一致,故,最好的作法使用表的別名重寫默認方法的名字,如:
select * from (values (1,'one'),(2,'two'),(3,'three')) as t(num, letter);
排序