隨便玩玩之PostgreSQL(第二章)單表數據查詢


隨便玩玩之PostgreSQL(第二章)單表數據查詢

未經授權不得轉載


第二章 單表數據查詢
數據庫的基本功能就是數據增查改刪,倘若不可以,要她還有什么意義。數據查詢功能不僅僅是查詢,而且還能篩選,並且格式化顯示。
數據查詢使用SELECT語句,本章介紹如何使用SELECT查詢(列出)數據庫中的數據。


2.1查詢數據庫cj表中全部信息
方法一:使用“*”通配符查詢所有數據(所有字段數據)。

SELECT * FROM cj;

結果如圖。



方法二:制定所有字段(列名)。每個字段用逗號(,)隔開。

SELECT id,kc,bj,xm,yw,sx,yy FROM cj;

結果如圖。


2.2查詢數據庫中指定字段信息(只顯示出想要的列)。
只要是表內的字段就可以,重復也可以,字段數量最多1664個。

SELECT xm,yw FROM cj;

結果列出所有學生的姓名和語文成績。




2.4查詢指定記錄(只顯示想要的行)。
數據庫的信息本來就包含了各種信息,如cj表中包括一班、二班、三班的每一個學生的考試成績。倘若查詢一班所有人的成績,可以查出所有人的成績,然后在EXCEL中刪掉二班、三班的。數據量少的時候可以這樣,數據量多的時候速度就會下降。不過,我們可以通過限制查詢條件進行查詢,按條件查詢(列出)數據。

SELECT * FROM cj WHERE bj='一班';

結果如圖。

 語句中的等號(=)表示只查詢bj字段為一班的學生的成績。等號為判斷符,其他判斷符為<>(或者!=,表示不等於),<(表示左邊數值小於右邊數值),<=(表示小於等於右邊數值),>(表示大於右邊數值),>=(表示大於等於右邊數值),BETWEEN AND(表示介於兩個數值之間)。
如:

 1 --查詢語文成績大於60的學生。
 2 SELECT * FROM cj WHERE yw > 60;
3 --查詢語文成績在60到69之間的學生。 4 SELECT id,bj,xm,yw FROM cj WHERE yw BETWEEN 60 AND 69; 5 --或者 6 SELECT id,bj,xm,yw FROM cj WHERE yw>=60 AND yw<69; --結果與第四行語句相同。
7 --查詢語文成績不是60到69的學生。 8 SELECT * FROM cj WHERE yw NOT BETWEEN 60 AND 69; 9 --或者 10 SELECT * FROM cj WHERE yw>69 OR yw <60;
11 --查詢英語成績等60的學生。 12 SELECT * FROM cj WHERE yy=60
13 --查詢英語成績等於60且必須等於70的學生(無意義,沒結果且不合邏輯)。 14 SELECT * FROM cj WHERE yy=60 AND yy=70;
15 --查詢張三的成績。 16 SELECT * FROM cj WHERE xm=’張三’;
17 --查詢張三其中考試的成績。 18 SELECT * FROM cj WHERE xm='張三' AND kc='期中考試';
19 --查詢語文成績大於80和(或)小於65的學生。 20 SELECT * FROM cj WHERE yw > 80 OR yw<65;

 

2.4多條件查詢
多條件查詢使用AND或OR操作符,可以指定2個及以上的條件。

AND操作符限定滿足所有條件才會有記錄返回。
如:查詢期中考試三班語文成績大於80的學生。

SELECT * FROM cj WHERE kc='期中考試' AND bj='三班' AND yw>80;

OR操作符只需所有條件中滿足一個條件即可。
如:查詢語文成績大於80或一班的學生。

SELECT * FROM cj WHERE yw>80 OR bj='一班';

用IN操作符實現OR操作符功能。
如:查詢英語成績等於60和(或)70的學生。

--OR操作符
SELECT * FROM cj WHERE yy=60 OR yy=70;
--IN操作符
SELECT * FROM cj WHERE yy in (60,70);

 2.5 去掉查詢結果中的重復記錄。
cj表中共有18個學生的信息,每一個信息都有一個班級。想要從表中得到有多少個班級,只有查詢出所有班級字段,然后去掉重復的,只保留一個,即可得到班級數量。使用DISTINCT關鍵字即可去掉重復記錄,只保留一個記錄值。

SELECT DISTINCT bj FROM cj;

結果如圖。

結果把所有的班級只列出一個,只需要數一數有多少行即可得出有三個班級。

也有不想數行的方法,使用count()函數即可實現。

SELECT  count(DISTINCT bj)  FROM cj;

結果如圖。


2.6對查詢結果排序
默認查詢結果沒有排序,有可能每次的查詢結果順序都不一樣。使用ORDER BY子句可以對結果進行排序。
如:從低到高列出所有學生的語文成績。

SELECT xm,yw,bj,kc FROM cj ORDER BY yw;

結果如圖。


如:先分期中考試、期末考試,在從低到高列出所有學生語文成績。

SELECT kc,yw,bj,xm FROM cj ORDER BY kc,yw;

結果如圖。


默認排序為1-9,A-Z,逆序排列只需要在字段后加DESC關鍵字即可,DESC約束其前的字段,如果對所有排序條件逆序,需在所有關鍵字后加DESC。
如:列出從高到低列出所有學生期中考試語文成績。

SELECT kc,yw,bj,xm FROM cj WHERE kc='期中考試' ORDER BY kc,yw DESC;

結果如圖。


2.7查詢結果分組
分組排序使用GROUP BY子句。
但是分組之后組字段顯示的值是什么?做班級成績匯報時,一般說一班有多少個人,語文平均分是多少,語文最高分是多少,最低分是多少,不會說出每個人的成績,也不會隨便說一個人的成績。所以分組之后顯示的是計算的結果,計算使用聚合函數。常用的聚合函數有:計數量count(),求最大值max(),求最小值min(),計總和sum(),求平均avg()。
如:計算出各班的期中考試平均。

SELECT bj,avg(yw),avg(sx),avg(yy) FROM cj WHERE kc='期中考試' GROUP BY bj;

結果如圖。


小數點太多?可以用round()函數截取。

SELECT bj,round(avg(yw),2),avg(sx),avg(yy) FROM cj WHERE kc='期中考試' GROUP BY bj;

結果如圖。

一行的SQL語句太長?可以分行寫SQL語句,只要在最后有一個分號就可以。

SELECT     bj,
         round(avg(yw),2),
         avg(sx),avg(yy)
    FROM cj
    WHERE kc='期中考試'
    GROUP BY bj;

結果如圖。

語句換行不影響查詢結果。


表頭都是AVG,不美觀?使用AS關鍵字設置別名即可。

SELECT     bj AS "班級",
         round(avg(yw),2) AS "語文平均分",
         avg(sx)  AS "數學平均分",
         avg(yy)  AS "英語平均分"
    FROM cj
    WHERE kc='期中考試'
    GROUP BY bj;

結果如圖。

AS的功能是給字段起一個別名。


數據沒有排序,看起來不方便?分組之后再排序。

SELECT     bj AS "班級",
         round(avg(yw),2) AS "語文平均分",
         avg(sx)  AS "數學平均分",
         avg(yy)  AS "英語平均分"
    FROM cj
    WHERE kc='期中考試'
    GROUP BY bj
    ORDER BY avg(yw);

結果如圖。

注:最后的ORDER BY指定的不是字段本身,而是使用聚合函數計算后的字段。已經給avg(yw)設置了別名,那么ORDER BY 能使用別名作為排序條件嗎?當然可以。

SELECT     bj AS "班級",
         round(avg(yw),2) AS "語文平均分",
         avg(sx)  AS "數學平均分",
         avg(yy)  AS "英語平均分"
    FROM cj
    WHERE kc='期中考試'
    GROUP BY bj
    ORDER BY "語文平均分";

結果如圖。


 

2.8查詢結果分組排序后再篩選
使用WHERE關鍵字可以篩選過濾數據,但是WHERE的篩選只能是指定選擇記錄的條件,請記住:WHERE關鍵字是用在記錄上的。對於分組之后的組有該如何篩選?HAVING關鍵字用來篩選分組之后的數據。
如:篩選出期中考試語文平均分大於70的班級。

SELECT   bj AS "班級",
             round(avg(yw),2) AS "語文平均分",
             avg(sx)  AS "數學平均分",
             avg(yy)  AS "英語平均分"
    FROM cj
    WHERE kc='期中考試'
    GROUP BY bj
    HAVING avg(yw)>70;        

結果如圖。


2.9限制查詢結果數量。
SELECT將返回所有匹配的行,可能是表中的所有行,如僅僅需要返回第一行或前幾行,使用LIMIT關鍵字。
如:查詢cj前3行的數據。

SELECT * FROM cj LIMIT 3;

結果如圖。


也可以查詢從第4行開始的3條記錄。

SELECT * FROM cj LIMIT 3 OFFSET 4;

結果如圖。


數據庫本身的記錄(行)從0開始計算,第4行應理解為數據庫的第5個記錄。


2.10 階段性總結示例:使用聚合函數實現分類匯總
count()函數計算表內行的總數。方法有兩種:count(*)計算表內行的總數,包括空值。Count(字段名)計算指定列行的總數,忽略空值。
sum()函數計算一個列的所有記錄累計總和。
avg()函數計算一個列的所有記錄的平均值。
Max()函數返回一個列的所有記錄中的最大值。
Min()函數返回一個列的所有記錄中的最小值。
如:分類匯總功能。

 1 SELECT   bj                          AS "班級"         ,
 2          count(xm)                   AS "人數"         ,
 3          round(sum(yw)/count(xm),2)  AS "語文"         ,
 4       -- round(avg(yw),2)            AS "語文"         ,
 5          max(yw)                     AS "語文最高分"    ,
 6          min(yw)                     AS "語文最低分"    ,
 7          round(avg(sx),2)            AS "數學平均分"    ,
 8          max(sx)                     AS "數學最高分"    ,
 9          min(sx)                     AS "數學最低分"    ,
10          round(avg(yy),2)            AS "英語平均分"    ,
11          max(yy)                     AS "英語最高分"    ,
12          min(yy)                     AS "英語最低分"
13     FROM cj
14     WHERE kc = '期中考試'
15     GROUP BY bj
16     ORDER BY avg(yw);

結果如圖。

使用方法非常靈活,一條語句搞定。


 

 2.11子查詢
子查詢是把一個查詢嵌套在另一個查詢中。子查詢又叫內部查詢,相對於內部查詢,包含着子查詢的叫外部查詢。
子查詢可以包含普通select可以包括的任何子句,比如:distinct、 group by、order by、limit、join和union等;但是對應的外部查詢必須是以下語句之一:select、insert、update、delete、set或 者do。
子查詢可以在SELECT后,FROM后,WHERE后,GROUP BY后和ORDER BY后。
根據返回值類型,子查詢分為標量子查詢(單一值子查詢,返回一個值)、列子查詢(返回一列值)、行子查詢(返回一行值)、表子查詢(返回一個表的值),
可以使用的操作符:= > < >= <= <> ANY IN SOME ALL EXISTS 。
2.11.1標量子查詢
標量子查詢返回一個值,可以與外部查詢使用=、>、<、>=、<=和<>符號進行比較判斷,如果子查詢返回的不是一個標量值,而外部查詢使用了比較符和子查詢的結果進行了比較,那么就會拋出異常。
如:查詢期中考試語文成績高於張三的學生。

1 SELECT * 
2     FROM cj 
3     WHERE yw > 
4         (SELECT yw FROM cj WHERE kc='期中考試' AND xm ='張三') 
5         AND kc='期中考試';

結果如圖:

得到的結果是把期中考試語文成績高於張三的學生全部列出來,最后的AND kc='期中考試'判斷條件是將結果限定在期中考試內,去掉這一句會列出期中考試和期末考試成績。

其執行循序為:先執行(SELECT yw FROM cj WHERE kc='期中考試' AND xm = '張三'),得到張三的期中考試語文成績,為64,再和yw>組成判斷表達式yw>64;yw>64和AND kc='期中考試'組成邏輯與表達式(兩個結果都為真),最后執行外部語句(整個語句)

關於子查詢請記住,語句里有括號,則先執行括號內部查詢(子查詢),得到結果,作為外部查詢的一部分,再執行部查詢

也可以把子查詢放在SELECT后。

如:查詢張三的期中考試和期末考試語文成績,以及兩者之間的差距。

SELECT  xm    AS "姓名" ,
        yw    AS "期中考試" ,
        (SELECT yw FROM cj WHERE kc='期末考試' AND xm='張三')       AS "期末考試" ,
        yw - (SELECT yw FROM cj WHERE kc='期末考試' AND xm='張三')  AS "差距"
    FROM   cj
    WHERE  kc='期中考試' AND xm='張三';

結果如下:

如上所釋,先執行括號內語句(子查詢),結果作為外部語句(整個語句)組成部分,再執行外部語句

2.11.2列子查詢

列子查詢返回一個列的數據,可以使用 = > < >= <= <> 這些操作符對子查詢的結果進行比較,通常子查詢的位置在比較式的右側。可以使用 IN、ANY、SOME 和 ALL 操作符,不能直接使用 = > < >= <= <> 這些比較標量結果的操作符。

ALL操作符是所有、全部的意思。只有全部符合條件,外部語句才有結果。例如,>(1,2,3)表示必須大於3。(注:NOT IN 與<>ALL等效)

如:查詢語文成績比數學最高分還高的同學。

SELECT
       xm     AS "姓名" ,
       yw     AS "語文成績" ,
       (SELECT max(sx) FROM cj)   AS "全部學生數學最高分"
    FROM cj
    WHERE yw > ALL (SELECT sx FROM cj);   --左邊大於右邊最大的

結果如圖。

ANY操作符是任意一個的意思。滿足任何一個即可。例如:>ANY(1,2,3)表示大於1即可。

SOME操作符與ANY相同。

如:查詢數學成績比語文最低分高的學生。

SELECT  xm  AS "姓名",
        sx  AS "數學",
        (SELECT min(yw) FROM cj)  AS "語文最低分"
    FROM cj
    WHERE sx > ANY (SELECT yw FROM cj)
    ORDER BY sx DESC;

結果如圖。

當判斷對象中一個是另一個的子集時,ANY與IN等效,結果一樣。

 2.11.3行子查詢

如:查詢表內信息是否在另一個表中完全一致。

SELECT * 
    FROM (SELECT * FROM cj WHERE id = 5) id5  --FROM后的子查詢得到一行數據
    WHERE (id,kc,bj,xm,yw,sx,yy) IN (SELECT * FROM cj);

結果如圖。

2.11.4表子查詢

結果得到一個表。

如:查詢所有學生的期中考試成績。

1 SELECT * 
2     FROM (SELECT * FROM cj WHERE kc='期中考試') kc_qz;
3 -- 和 SELECT * FROM cj WHERE kc='期中考試'; 語句的執行結果相同,不同的是查詢的表不一樣。

結果如下。

代碼內有注釋。結果相同,查詢的表不相同。行3的語句是直接從cj表內查詢;行2的語句是執行一個查詢,得到的結果為表。

注:給表起別名只需在表后加空格和名稱。

 2.11.5 階段性總結示例:利用子查詢求班級平均分差距。

 1 SELECT kc_qz.bj    AS "期中班級"                          ,
 2        kc_qm.bj    AS "期末班級"                          , 
 3     -- 增加班級一列(kc_qm.bj),用來識別班級,無特殊意義
 4        round(kc_qz.yw1,2)                AS "期中語文"    ,
 5        round(kc_qm.yw2,2)                AS "期末語文"    , 
 6        round(kc_qm.yw2-kc_qz.yw1,2)      AS "語文差距"    , 
 7     -- 分數差距,正數表示期末考試相對期中考試有提升,負數表示下降
 8        round(kc_qz.sx1,2)                AS "期中數學"    ,
 9        round(kc_qm.sx2,2)                AS "期末數學"    ,
10        round(kc_qm.sx2 - kc_qz.sx1,2)    AS "數學差距"    ,
11        round(kc_qz.yy1,2)                AS "期中英語"    ,
12        round(kc_qm.yy2,2)                AS "期末英語"    ,
13        round(kc_qm.yy2 - kc_qz.yy1,2)    AS "英語差距"
14     FROM
15         (SELECT bj,
16                 avg(yw) AS "yw1",
17                 avg(sx) AS "sx1",
18                 avg(yy) AS "yy1"
19             FROM cj
20             WHERE kc='期中考試'
21             GROUP BY bj) kc_qz,
22         (SELECT bj,
23                avg(yw) AS "yw2",
24                avg(sx) AS "sx2",
25                avg(yy) AS "yy2"
26             FROM cj
27             WHERE kc='期末考試'
28             GROUP BY bj) kc_qm
29     WHERE  kc_qz.bj = kc_qm.bj      -- 表連接查詢,下一章內容
30     ORDER BY kc_qz.bj;

結果如圖。

看起來是30行,實際上只是一條語句。

 

至此,第二章結束,簡單介紹了單表查詢,語句都很簡單,但是很神奇。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM