SQL語法(下)

接續上篇 SQL 語法(上)

更新的語法

更改其中一筆資料的內容,一定要設條件不然所以資料都會被修改:

UPDATE heroes
SET age=10
WHERE  id=25;

也可以多筆項目更新,一定要設條件除非要更新全部資料:

UPDATE heroes
SET age=10, hero_level= "A", hero_rank =5
WHERE  id=25;
計算

計算在 heroes 資料表裡的 hero_level 欄位等於A的 id 欄位次數有多少,是算次數不是把 id 值加總:

SELECT count(id)
FROM heroes
WHERE hero_level="A";

把 heroes 資料表裡的 hero_level 欄位等於S的年齡加總起來:

SELECT sum(age)
FROM heroes
WHERE hero_level="S";

把 heroes 資料表裡的 hero_level 欄位等於S的年齡加總起來後,除與筆數得到平均數:

SELECT avg(age)
FROM heroes
WHERE hero_level="S";

把 heroes 資料表裡,年齡最大的是誰:

SELECT name,max(age)
FROM heroes;

理所當然也有年齡最小的是誰:

SELECT name,min(age)
FROM heroes;
分組與排序

依 heroes 資料表裡的 hero_level 欄位來分,去掉重複性:

SELECT DISTINCT hero_level
FROM heroes;

依 heroes 資料表裡的 hero_level 欄位來分組,並顯示個組年齡是多少:

SELECT hero_level, sum(age)
FROM heroes
GROUP by hero_level;
  • DISTINCT 與 GROUP by 的差別,在與 DISTINCT 針對單一欄位來去掉重複性,不能像 GROUP by 一樣分組後,還能做計算或多欄位子句結合,如果單純只想查看註冊用戶裡的地區有哪些,可以用 DISTINCT 就好,沒有要做其他查詢與計算。

把 heroes 資料表裡 hero_level 欄位值等於S的資料挑出來,再依據 hero_rank 欄位進行排序,把所以欄位顯示出來,ORDER by 沒有額外寫後面的 DESC 會是正向排序,有寫 DESC 就會是反向排序:

SELECT *
FROM heroes
WHERE hero_level = "S"
ORDER by hero_rank DESC;

也可以運用 ORDER by 來選取前三筆資料

SELECT *
FROM heroes
WHERE hero_level = "S"
ORDER by  hero_rank
LIMIT 3;

還可以隨機選取三筆資料:

SELECT *
FROM heroes
ORDER by random()
LIMIT 3;
關聯性查詢

monsters 資料表裡 kill_by 欄位裡的 id 值,與 heroes 資料表的 id 欄位的值比對,我要 heroes 資料表 name 欄位等於埼玉的資料,所以只要 name 等於埼玉的 id 找到,就會把在 monsters 資料表裡,kill_by 欄位裡的 id 與埼玉 id 一樣的資料挑選出來:

SELECT *
FROM monsters
WHERE kill_by = (
SELECT id
FROM heroes
WHERE name="埼玉"
);

當然挑件也可以增加,找到 name 欄位等於埼玉或傑諾斯的 id:

SELECT *
FROM monsters
WHERE kill_by in (
    SELECT id
    FROM heroes
    WHERE name  in ("埼玉","傑諾斯")
);

也可以計算找出的資料筆數,如果單純只想知道數量:

SELECT count(*)
FROM monsters
WHERE kill_by in (
    SELECT id
    FROM heroes
    WHERE name  in ("埼玉","傑諾斯")
);

以下為連結(join)的方法運用

  • 第一種:

與剛剛的子查詢要查詢的資料一樣,第一個資料表會放在左邊,INNER JOIN 後的資料表會在右邊,兩個資料表會基於 on 的條件比對,只會顯示有對到的資料:

SELECT *
FROM heroes
INNER JOIN monsters
on heroes.id = monsters.kill_by;

當然也可以選擇自己想要的欄位:

SELECT  heroes.name ,monsters.name
FROM heroes
INNER JOIN monsters
on heroes.id = monsters.kill_by;

第二種:

因爲是 LEFT JOIN 會以左邊的資料表為主來顯示全部資料,右邊的資料表如果有比對到就會有資料,沒有就會顯示 NULL:

SELECT *
FROM heroes
LEFT JOIN monsters
on heroes.id = monsters.kill_by;

還可以加條件把 monsters 資料表裡 monsters.kill_by 等於 NULL 刪除,等同於 INNER JOIN 只顯示有比對到的資料:

SELECT *
FROM heroes
LEFT JOIN monsters
on heroes.id = monsters.kill_by
WHERE monsters.kill_by NOT NULL;

也可以把 monsters 資料表裡 monsters.kill_by 等於 NULL 的資料留下,意思是 heroes 資料表裡有跟 monsters 比對到的資料都剔除,只剩下沒比對到的資料:

SELECT *
FROM heroes
LEFT JOIN monsters
on heroes.id = monsters.kill_by
WHERE monsters.kill_by is NULL;

第三種: 有以左邊為主的就也會有以右邊為主的資料表顯示,不過 SQLite 不支援 RIGHT JOIN,此時用 LEFT JOIN 再把兩個資料表位置對調,得到的答案是一樣的。

SELECT *
FROM heroes
RIGHT JOIN monsters
on heroes.id = monsters.kill_by;

第四種: 左右資料表的資料合併所有記錄,如果缺少匹配的記錄,即以 NULL 填充,SQLite 不支援。

SELECT *
FROM heroes
FULL OUTER JOIN monsters
on heroes.id = monsters.kill_by;

與第一種要的資料完全相反,第一種只會顯示有對到的資料,這個不要對到的資料:

SELECT *
FROM heroes
FULL OUTER JOIN monsters
on heroes.id = monsters.kill_by
WHERE monsters.kill_by is NULL OR heroes.id is NULL

可以參考此圖: 可以參考此圖

comments powered by Disqus