---
# System prepended metadata

title: 20200717 Astro Camp SQL
tags: [Astro Camp, ' SQL']

---

---
title: 20200717 Astro Camp SQL
tags: Astro Camp, SQL
---

# 20200717 Astro Camp SQL

一個資料庫會有很多個表格
像是一個EXCLE有很多分頁
資料庫可以將多個表格互相串連
EXCLE不行

**RDBMS
關聯資料管理系統
Relational DataBase Management Systems**


NoSQL 非關聯式系統
如果只存放資料，不需要做資料中的交叉作用的話，可以用NoSQL


## 建立資料庫
`create database 資料庫名稱;`

## 使用資料庫
`use 資料庫名稱;`
接下來才能在此資料庫裡作查詢

## 表格調整
`alter table`
`change `重新命名

## 刪除資料表
`drop table "資料表名稱"`

DDL/DML/DQL


## 新增資料
`insert into heroes
(name, hero_level, description)
vaule
("琦玉", "C", "任何敵人一拳擊敗");`

一個蘿蔔一個坑，欄位順不重要，有指定就好
沒填入的欄位預設值要看作業系統或欄位型態。

將單引號當字串：在單引號後加上反斜線`"\"`，表示此單引號為純粹的字串，不列入程式語言計算。
eg.
`'speed o'\s sound sonic'`

## 查詢資料
`SELECT * FROM (資料表);`
從特定資料表列出特定資料。
 "*"萬用字元
 
## 過濾資料
`SELECT * FROM (資料表) where 追加條件;`

`SELECT * FROM heroes where hero_level = 's' AND gender ="F";`

用`AND`來連接不同的條件


---


`SELECT name, gender FROM heroes WHERE hero_level = 'S'`
挑出英雄等級為S的名字與性別欄位。

`SELECT * ` 全選欄位，比較占記憶體，效能慢一點。

`SELECT * FROM heroes WHERE age IS null;`
誰沒有填年紀。

### 搜尋關鍵字 
`SELECT * FROM heroes WHERE name LIKE '%背心%';`
從英雄資料表中找出名字裡面有背心的英雄。

%代表任意字元
`WHERE name LIKE %背心`   找出XXXX背心的英雄
`WHERE name LIKE 背心%`   找出背心XXXX的英雄

---
### 搜尋兩個條件以上

1.列出10~25歲的英雄
SQL 沒有range 或10..25的語法，所以搜尋10~25歲的人要拆成兩個條件：
`SELECT * FROM heroes WHERE age >= 10 AND age <= 25 ; `

2.列出S級與A級的英雄
`SELECT * FROM heroes WHERE hero_level ='S' OR hero_level = 'A'; `
`AND` 相當於 `&&` 兩個條件都滿足才會被挑出
:::info
推薦寫法：
`SELECT * FROM heroes WHERE hero_level IN ('S', 'A')`
:::
3.列出不是S級的英雄
`SELECT * FROM heroes WHERE hero_level <>'S' `

4.列出不是S也不是A的英雄(可以用`<>'S' AND <>'A'`)

`SELECT * FROM heroes WHERE hero_level NOT IN ('S','A');`

## 更新資料
1.把id為25的英雄年齡更新成10歲
`UPADATE heroes SET age = 10 WHERE id = 25;`
:::info
Rails
`@hero = Hero.find(25)`
`@hero.update(age:10, level:'A')`
:::

2.多重條件
`UPADATE heroes SET age = 10, hero_level = 'A' WHERE id = 25;`

3.所有人老一歲
`UPDATE heroes SET age = age + 1`

因為是大範圍更動(沒有WHERE)，MySQL不讓過，要將安全模式關掉，才可以更新。
`SET SQL_SAFE_UPDATES = 0`
*SQLite會過！*

## 刪除資料

因為資料庫無法管控，(git 管控的是資料庫的migration(結構)，管不到裡面的資料)，所以一般會多加一個欄位is_delete?(boolen)。
當要刪除資料的時候會更改此欄位，將false改成true，以示刪除。

## 計算資料
### 資料總數
計算所有A級英雄總數，並設定成CC的欄位
`select count(*) as CC
FROM heroes
where hero_level = 'A';`

### 加總資料
`SELECT SUM(age)
FROM heroes
WHERE hero_level = 'A' AND IS NOT NULL;`

### 平均資料
`SELECT avg(age)
FROM heroes
WHERE hero_level = 'A' AND IS NOT NULL;`

rails版：
`Hero.average(hero_level:'A').average(:age)`

### 最大值 最小值
`SELECT MAX(age) FROM heroes`
`SELECT MIN(age) FROM heroes`

### 分組
`SELECT hero_level, avg(age)
FROM heroes
GROUP BY hero_level;`
從資料裡面用英雄等級分組(GROUP BY )
並顯示出英雄等級、平均年齡(SELECT hero_level, avg(age))

### 挑調重複的
`select distinct hero_level from heroes`

### 排序
`select * from heroes where hero_level ='S' ORDER BY hero_rank (DESC)`

DESC 反向排序(由大到小)

## 多個資料表查詢
```
SELECT name, danger_level
FROM monster
Where kill_by IN（
select id 
from heroes
where name in ('琦玉', '傑諾斯')
）
```

## join 交集 (時間軸：16:20)
```
SELECT monster.name, monster.danger_level, hero.name
FROM monster                     (left)
LEFT JOIN heroes                 (right)
ON monster.kill_by = hero.id     (ON 後面加上 join 的條件)
WHERE monster.kill_by IS NOT NULL AND hero.hero_level = 'S'
```

`left join` (有點像留住left那一塊的join方式)

當你`from monster`時，`monster`資料庫便是左方的資料庫，`left join`就會以此資料庫為主，`join`進去的資料若無符合 `ON` 條件，便不會被挑選出來。

`right join` 會以右邊的資料庫為主，原來資料庫裡未符合`ON`條件的不會被顯示。


## union










