1. sql92的
SELECT ename,dname FROM ept AS e , dept AS d WHERE e.dept_id=d.id
其中","就是笛卡爾積在sql92中
2. sql99的 須要 一個關鍵字 "join" 來實現笛卡爾積 (內鏈接 的 等值鏈接)
SELECT
e.ename,
d.dname
FROM
ept e
JOIN dept d ON e.dept_id = d.id
只是省略了 inner 這個關鍵字
SELECT
e.ename,
d.dname
FROM
ept e
INNER JOIN dept d ON e.dept_id = d.id
複製代碼
等值鏈接(鏈接條件是 a.filed=b.filed)前端
1. 需求 : 根據員工表的部門名稱id查詢出部門表中部門名稱
2.查詢出 員工表的員工名稱和部門id
mysql> select ename,dept_id from ept;
+-------+---------+
| ename | dept_id |
+-------+---------+
| 小明 | 1 |
| 小王 | 2 |
| 小李 | 3 |
| 小錢 | 2 |
+-------+---------
3. 查詢出了 部門表中部門名稱和部門id
mysql> select id , dname from dept;
+----+-------+
| id | dname |
+----+-------+
| 1 | 運維 |
| 2 | 開發 |
| 3 | 產品 |
| 4 | 前端 |
+----+-------+
4. 咱們能夠將兩個錶鏈接起來 而後 第一章標的dept_id=B表的id 就行了,這就是等值鏈接
SELECT
e.ename,
d.dname
FROM
ept e
INNER JOIN dept d ON e.dept_id = d.id
+-------+-------+
| ename | dname |
+-------+-------+
| 小明 | 運維 |
| 小王 | 開發 |
| 小李 | 產品 |
| 小錢 | 開發 |
+-------+-------+
複製代碼
非等值鏈接 (鏈接條件不是等值)mysql
SELECT
e.ename,e.salary,s.level
FROM
ept e
INNER JOIN
salary_level s
ON
e.salary BETWEEN s.salary-449 AND s.salary
複製代碼
自鏈接(本身連本身) 把兩次查詢的結果當作單獨的表sql
mysql> select ename,p_id from ept;
+-------+------+
| ename | p_id |
+-------+------+
| 小明 | NULL |
| 小王 | 1 |
| 小李 | 2 |
| 小錢 | 1 |
+-------+------+
mysql> select id , ename from ept;
+----+-------+
| id | ename |
+----+-------+
| 1 | 小明 |
| 2 | 小王 |
| 3 | 小李 |
| 4 | 小錢 |
+----+-------+
咱們能夠當作 第一個表爲 A表 ;第二個表爲B表;只要A表的 p_id 等於 B 表的 id 就能夠實現了
SELECT
a.ename,
b.ename as leader_name
FROM
ept a
INNER JOIN ept b ON a.p_id = b.id
+-------+-------------+
| ename | leader_name |
+-------+-------------+
| 小王 | 小明 |
| 小錢 | 小明 |
| 小李 | 小王 |
+-------+-------------+
複製代碼
什麼是外鏈接?shell
咱們不難發現 咱們在等值鏈接中只會取到A和B表都符合條件的內容;這就是內鏈接數據庫
有的時候咱們須要 咱們也要查詢出B表中應該有的數據可是沒匹配的數據api
因此區分 內外鏈接的關鍵字是 left 和 rightbash
左外鏈接(LEFT JOIN/LEFT OUTER JOIN)oracle
同上面 內鏈接那個需求,咱們須要顯示出沒有領導的員工
SELECT
a.ename,
b.ename AS leader_name
FROM
ept a
LEFT JOIN ept b ON a.p_id = b.id
+-------+-------------+
| ename | leader_name |
+-------+-------------+
| 小王 | 小明 |
| 小錢 | 小明 |
| 小李 | 小王 |
| 小明 | NULL |
+-------+-------------+
複製代碼
右外鏈接(right JOIN/right OUTER JOIN)app
1. 需求: 查詢出部門對應的員工姓名,沒有的也要顯示
2.查詢出 員工表的員工名稱和部門id
mysql> select ename,dept_id from ept;
+-------+---------+
| ename | dept_id |
+-------+---------+
| 小明 | 1 |
| 小王 | 2 |
| 小李 | 3 |
| 小錢 | 2 |
+-------+---------
3. 查詢出了 部門表中部門名稱和部門id
mysql> select id , dname from dept;
+----+-------+
| id | dname |
+----+-------+
| 1 | 運維 |
| 2 | 開發 |
| 3 | 產品 |
| 4 | 前端 |
+----+-------+
4. 咱們就須要 B表所有顯示;就算不匹配的
SELECT
d.dname,
e.ename
FROM
dept d
LEFT JOIN ept e ON d.id = e.dept_id
+-------+-------+
| dname | ename |
+-------+-------+
| 運維 | 小明 |
| 開發 | 小王 |
| 產品 | 小李 |
| 開發 | 小錢 |
| 前端 | NULL |
+-------+-------+
因此 不難看出來 咱們的需求實現了;就算是前端麼有人,可是他也所有顯示了;
5. 其中關於左和右 是創建在 join 這個詞 左邊仍是右邊的 你的表在join這個詞左邊就是左鏈接
複製代碼
1. 需求 咱們須要 查詢出每一個員工對應的領導名稱,以及每一個員工對應的部門名稱,以及每一個員工對應的薪水等級
2. 三張表結構
mysql> select * from ept ;
+----+-------+---------+---------+------+
| id | ename | salary | dept_id | p_id |
+----+-------+---------+---------+------+
| 1 | 小明 | 1800.00 | 1 | NULL |
| 2 | 小王 | 1200.00 | 2 | 1 |
| 3 | 小李 | 2500.00 | 3 | 2 |
| 4 | 小錢 | 2000.00 | 2 | 1 |
+----+-------+---------+---------+------+
mysql> select * from dept ;
+----+-------+
| id | dname |
+----+-------+
| 1 | 運維 |
| 2 | 開發 |
| 3 | 產品 |
| 4 | 前端 |
+----+-------+
mysql> select * from salary_level;
+----+--------+-------+
| id | salary | level |
+----+--------+-------+
| 1 | 2500 | 1 |
| 2 | 2000 | 2 |
| 3 | 1500 | 3 |
| 4 | 1000 | 4 |
+----+--------+-------+
3. 咱們須要 a錶鏈接a表 a錶鏈接b表 a錶鏈接c表
select
a.ename,b.ename as leader_name,c.dname as dept,d.level as level
from ept a
left join ept b
on a.p_id=b.id
join dept c
on a.dept_id=c.id
join salary_level d
on a.salary between d.salary and d.salary+499;
+-------+-------------+------+-------+
| ename | leader_name | dept | level |
+-------+-------------+------+-------+
| 小李 | 小王 | 產品 | 1 |
| 小錢 | 小明 | 開發 | 2 |
| 小明 | NULL | 運維 | 3 |
| 小王 | 小明 | 開發 | 4 |
+-------+-------------+------+-------+
複製代碼
1. 需求 查詢出員工表中薪水大於平均薪水的員工的姓名和薪水
2. 查詢emp 表 狀況
mysql> select * from emp;
+-------+--------+-----------+------+------------+---------+---------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+--------+-----------+------+------------+---------+---------+--------+
| 7396 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 |
| 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 |
| 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
| 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
| 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 30 |
| 7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL | 30 |
| 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 20 |
| 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 |
| 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
| 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 | 0.00 | 30 |
| 7876 | ADAMS | CLERK | 7788 | 1987-05-23 | 1100.00 | NULL | 20 |
| 7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950.00 | NULL | 30 |
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
| 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300.00 | NULL | 10 |
+-------+--------+-----------+------+------------+---------+---------+--------+
3. 就是嵌套查詢
SELECT
a.ENAME,
a.SAL
FROM
emp a
WHERE
a.SAL > (
SELECT
AVG(emp.SAL) AS avgsal
FROM
emp
)
+-------+---------+
| ENAME | SAL |
+-------+---------+
| JONES | 2975.00 |
| BLAKE | 2850.00 |
| CLARK | 2450.00 |
| SCOTT | 3000.00 |
| KING | 5000.00 |
| FORD | 3000.00 |
+-------+---------+
複製代碼
1. 需求 找出每一個部門的平均薪水,而且顯示出每一個部門的薪水等級
2. 分析 找出每一個部門的平均薪水 就須要 先按部門分組,而後求出每一個部門的平均薪水
SELECT
e.DEPTNO as DEPTNO,
AVG(e.SAL) AS avgsal
FROM
emp e
GROUP BY
e.DEPTNO
+--------+-------------+
| DEPTNO | avgsal |
+--------+-------------+
| 10 | 3150.000000 |
| 20 | 2220.833333 |
| 30 | 1566.666667 |
+--------+-------------+
3.查看薪水錶
mysql> select * from salgrade;
+-------+-------+-------+
| GRADE | LOSAL | HISAL |
+-------+-------+-------+
| 1 | 700 | 1200 |
| 2 | 1201 | 1400 |
| 3 | 1401 | 2000 |
| 4 | 2001 | 3000 |
| 5 | 3001 | 9999 |
+-------+-------+-------+
4. 咱們應該把 表1當作 a表 表二當作 b表 此時作鏈接
select a.DEPTNO,b.GRADE
from a
join b
on a.avgsal between b.LOSAL and b.HISAL
此時咱們是否是 能夠改寫一下
SELECT
a.DEPTNO,
a.avgsal,
b.GRADE
FROM
(
SELECT
e.DEPTNO AS DEPTNO,
AVG(e.SAL) AS avgsal
FROM
emp e
GROUP BY
e.DEPTNO
) a
JOIN salgrade b
ON a.avgsal BETWEEN b.LOSAL AND b.HISAL;
+--------+-------------+-------+
| DEPTNO | avgsal | GRADE |
+--------+-------------+-------+
| 10 | 3150.000000 | 5 |
| 20 | 2220.833333 | 4 |
| 30 | 1566.666667 | 3 |
+--------+-------------+-------+
複製代碼
1.使用場景 : 鏈接兩個同樣的表;運維
1. 查詢出工做爲 "CLERK" 和 "SALESMAN"的 員工姓名
2. 第一種實現結果
SELECT
ename,
job
FROM
emp
WHERE
JOB = "CLERK"
OR JOB = "ANALYST"
3. 第二種實現
SELECT
ename,
job
FROM
emp
WHERE
job IN ('CLERK', 'ANALYST')
4. 第三種實現
SELECT
ename,
job
FROM
emp
WHERE
job = "CLERK"
UNION
SELECT
ename,
job
FROM
emp
WHERE
job = "ANALYST"
+--------+---------+
| ename | job |
+--------+---------+
| SMITH | CLERK |
| ADAMS | CLERK |
| JAMES | CLERK |
| MILLER | CLERK |
| SCOTT | ANALYST |
| FORD | ANALYST |
+--------+---------+
顯然 union 必須 要求兩個組合的 表 必須 字段長度相同 ;並且 有意義點的就是 兩個表 字段含義同樣
複製代碼
非空約束 not null
惟一性約束 , 不可重複 unique
給約束起別名 constraint name
聯合約束主鍵約束 primary key 與 not no unique 的效果相同 ,
還能夠添加索引 ,每張表必須有主鍵,否則就是無效表
主鍵值不能修改的單一主鍵聯合主鍵(可是 一張表只能有一個主鍵,,只有兩個同樣時纔會出現主鍵不一樣)天然主鍵業務主鍵自增主鍵值 auto_increment 只要你一旦使用過 , 就不能重複使用外鍵約束 foreign key 外簡約束外鍵字段外鍵值
drop table if exists t_user;
create table t_user(
id int(2) not null,
name varchar(10) unique,
email varchar(20),
phone varchar(15),
cd_card char(18) not no unique,
constraint t_user_email_phone_unique unique(email,phone),
primary key(id,name)
)
constraint 英文單詞 翻譯叫 約束 通常寫法就是 constraint + 一個字段名 +條件
若是咱們給一個表添加外鍵約束
子 ----- 父
constraint t_student_classes_fk foreign key(classno) references t_class(cno)
子表的數據也就是 外鍵值能夠爲空 ,稱爲孤兒數據
父表中的引用字段必須具備惟一性
建立表要先建立父表再建立子表
複製代碼
1.級聯刪除 on delete cascade (當我刪除 父表(引用表)中的數據時,子表中的相關數據也要被刪除 )
cascade 意思是 級聯 ,瀑布
2.給學生表添加一個級聯刪除
alter table student drop foreign key t_student_classes_fk;
alter table stadent add constraint t_student_classes_fk foreign key(classno)
reference t_class(cno) on delete cascade;
3.級聯更新 on update cascade (更新父表,子表中引用的字段也要被更新)
alter table student add constraint t_class_student_fk foreign key(classno)
reference t_class(cno) on update cascade
* 注意就是 更新和刪除創建在外鍵之上
複製代碼
mysql數據庫中 在操做數據庫時 是 設置的自動提交事務
你能夠 根據 show variables like '%commit%'
; 看到
mysql> show variables like '%commit%';
+-----------------------------------------+-------+
| Variable_name | Value |
+-----------------------------------------+-------+
| autocommit | ON |
| binlog_group_commit_sync_delay | 0 |
| binlog_group_commit_sync_no_delay_count | 0 |
| binlog_order_commits | ON |
| innodb_api_bk_commit_interval | 5 |
| innodb_commit_concurrency | 0 |
| innodb_flush_log_at_trx_commit | 1 |
| slave_preserve_commit_order | OFF |
+-----------------------------------------+-------+
8 rows in set, 1 warning (0.00 sec)
複製代碼
開啓事務
1.手動開啓事務
start transaction ;
2. 執行 DML語句
inset into student (name) values ('小王');
3.手動提交
commit;
4.若是咱們關閉事務 set autocommit=off
執行 DML語句
而後 commit;
複製代碼
mysql的四種 隔離級別
1. 查看當前會話的隔離級別
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set, 1 warning (0.00 sec)
2. 查看當前 全局的隔離級別
mysql> select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| REPEATABLE-READ |
+-----------------------+
1 row in set, 1 warning (0.00 sec)
修改全局的隔離級別
set global transaction isolation level read committed
3. 讀未提交(read uncommitted) : 就是當A選擇開啓事務,執行了一條DML語句,此時未提交;而後B也開起了事務去讀取數據,結果讀取到了A修改後的數據,這條數據 爲 髒讀;
4. 讀已提交(read committed) : 就是A選擇開起了事務,而後執行了一條DML語句,此時開着事務的B沒法看到A執行後的結果,當A提交後,此時開着事務的B 就能看到 commit後的數據; 此時出現的現象叫作 不可重複讀;
5. 可重複讀(repeatable read) : 就是A,B開啓着事務,A提交的數據,B沒法獲取到 ;此時這種現象叫作幻象讀;保證了B的數據開啓事務時刻數據的一致性
6. 串行化(serializable): 同一時刻操做數據庫的只有一我的;可是能夠多人開啓事務;只能等待第一我的提交事務或者回滾事務,另一我的才能執行數據庫操做;
複製代碼
主鍵索引 ,添加主鍵會自動添加主鍵索引
外鍵索引,
索引檢索方式
不多使用 dml操做時,適合添加索引
常常出如今where語句中
建立索引
create index tudent_name_index on student(name);
查看索引
show index from table_name
刪除索引
drop index tudent_name_index on student;
複製代碼
索引也要被存儲在文件中
建立視圖
1. create view student_view as select * from student
2. 當咱們 show create view student_view時
mysql> show create view dept_view;
| View | Create View
| dept_view | CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `dept_view` AS select `dept`.`DEPTNO` AS `DEPTNO`,`dept`.`DNAME` AS `DNAME`,`dept`.`LOC` AS `LOC` from `dept` | gbk | gbk_chinese_ci
咱們能夠發現 他只是 在原有的表上建立了一個 select 語句
3. 刪除視圖
drop view dept_view;
或
drop view if exists dept_view;
複製代碼
索引 視圖 和 原表中的數據 是個影子關係
視圖的做用
隱藏表的細節 好比 create view dept_view as select depton as a ,dname as b from dept
咱們會發現 咱們拿到的表 只有 a , b 字段 只能考 字段操做
相似與 建立臨時表,提升查詢效率,以及可用性,
create view emp_dept as
select a.ename,b.dname
from emp a
join dept b
on a.deptno=b.deptno
而後直接
select* from emp_dept;
這個能夠提升檢索效率和重複利用率
複製代碼
mysql> show engines ;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine | Support | Comment | Transactions | XA | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| InnoDB | DEFAULT | Supports transactions, row-level locking, and foreign keys | YES | YES | YES |
| MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO |
| MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO |
| BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO |
| MyISAM | YES | MyISAM storage engine | NO | NO | NO |
| CSV | YES | CSV storage engine | NO | NO | NO |
| ARCHIVE | YES | Archive storage engine | NO | NO | NO |
| PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO |
| FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
9 rows in set (0.01 sec)
1. 默認是 innodb
2. 能夠修改 my.ini 設置默認存儲引擎 以及一些默認配置
3. 修改表的存儲引擎 alter table table_name engine=MyISAM
複製代碼
1.主要記住 innodb 支持事務操做
2. 使用**外鍵** 以及 級聯刪除和級聯更新也須要使用 innodb engine
複製代碼
3. 行及鎖定
4. mysql數據庫崩潰 後 提供自動恢復
5. 表空間的概念
6. 提供 acid 的兼容
複製代碼
1. 表存儲格式
- 表結構 .frm
- 表數據 .myd
- 表索引 .myi
2. 能夠壓縮文件,節省空間
複製代碼
lock table clazz read
; 此時只能讀數據,沒法修改數據;只有當 unlock tables; 才能夠執行修改操做lock table clazz write
; 此時只能寫數據,沒法進行讀取數據;只有當 unlock tables; 才能夠執行修改操做他不鎖住整個數據庫,開啓事務,只會鎖住操做的同一張表(好比 A B 兩我的同時開啓事務,A對錶a操做,B對錶b操做,此時兩個行爲均可以執行,不須要等待一方commit,當B表嘗試修改A表時;此時就會等待,必須等待A提交才能執行)
其實就是上面的四種事務;這裏不作解釋了;
1. 就是mysql默認的事務等級
他能保證 每一時刻只能有一我的操做數據庫,除非你提交了;否則沒法更新
好比 兩我的 A和B
每次執行操做 都要開啓事務 默認事務是 可重複讀(repeatable read) 這個級別;
count=2
當 A 執行 update oreders set count=count-1 where id=1 and count>=1;
此時 B也去執行 update oreders set count=count-2 where id=1 and count>=2;
因爲A先執行 ;因此此時B 是卡住的;只有 A提交了;B才能修改;此時 B中查到的count數據已經修改過了;因此返回結果爲false;
可是 在事務中 若是使用了 這個 select * from oreders for update; 他能夠防止讀取到的數據發生不可重複讀現象;其實能夠理解爲 帶着 update的select語句; 你執行了 update 自己就鎖住了;他其實一句帶着兩句;他是個 互斥鎖;你就算你是讀,可是你執行了這個操做,別人也沒法寫執行;
可是 就算是咱們在 開啓事務中 使用select * from oreders 讀到的是假數據 仍然不影響咱們執行 update操做時;數據的讀取問題 ;好比上面那個問題
複製代碼
1. 好比說 咱們在 查詢的時候 帶上一個 version ,更新的時候 須要帶上這個version
SELECT count,version FROM orders WHERE id =1 把查詢到version數據加給第二行,
每次更新都須要這樣子,若是一我的更新成功,那麼version數據就變化了,那麼另一我的拿到的鎖,他打不開,找不到數據就沒法更新
UPDATE orders SET count=count-5 , version=version+5 WHERE id=1 AND version=2 AND count>=5
這樣能夠防止超賣和加鎖
複製代碼
between range_1 and range_2 是 左閉右閉
SELECT
AVG(emp.SAL) AS avgsal,ENAME,SAL
FROM
emp
WHERE SAL>avgsal
切記 where 語句中不能直接套用非表格字段 ;這個須要子查詢
複製代碼
limit 用法 limit a , b (a是從0開始的,b指的是長度) 當 只有一個參數時 ;指的 是長度; 好比說 找出 第五個到第八個,咱們 5 , 6 , 7 ,8 一共長度是4 ,則 limit 4 , 4, 其中limit是mysql 特有的
mysql 的 varcart類型 長度 爲 1 能夠輸入 一個漢字 也是一個英文 一個數字 ;其實 一個varchar 就是一個字符;存儲空間等於實際數據長度
char 是固定長度 通常填寫 固定長度的信息好 ;存儲空間是死的;無論你是1 23 4 5 我規定了10 你就給你分配10
int類型 佔用4個字節 長度 好像無論寫多少 數字 都麼限制
bigint類型 佔用8個字節 長度 好像無論寫多少 數字 都麼限制
tinyint 類型 長度 選擇 1 可是能夠到達 127 [0,128)
double 和 float
date 佔用8個字節
備份表 : create table emp_bak as select * from emp
查看建立表的語句: show create table emp_bak
DML 是什麼 Data Manipulation Language(數據操縱語言) ; 很顯然是 delete , insert , update
delete from table_name where field=a
delete from table_name
update table_name set gender=1,emp=2 where id=1
insert into table_name(filed1,field2) values ('','','')
str_to_date('1949-10-01','%Y-%m-%d')
這個是日期 插入日期 ;; 其中mysql 默認的日期格式 是 1994-10-01
輸入這個不會報錯
show variables like '%char%';
+--------------------------+---------------------------------------------------------+
| Variable_name | Value |
+--------------------------+---------------------------------------------------------+
| character_set_client | gbk |
| character_set_connection | gbk |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | gbk |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | C:\Program Files\MySQL\MySQL Server 5.7\share\charsets\ |
+--------------------------+---------------------------------------------------------+
character_set_results 字符結果集
character_set_database 數據庫的字符集
修改很簡單 直接 set character_set_results = utf8 就能夠了
複製代碼
兩個表之間備份插入 ,上面提到了 所有插入 ,如今改爲條件插入insert into emp_bak select * from emp where job="manager"
數據庫模式定義語言DDL(Data Definition Language),是用於描述數據庫中要存儲的現實世界實體的語言。
添加 alter table table_name add email varchar(128) ;
修改 alter table table_name modify no int(8);
刪除 alter table table_name drop email ;
修改表結構 alter table table_name change name username varchar(32)
複製代碼
解決 1對 1 表的問題 :
查看數據庫的version SHOW VARIABLES WHERE Variable_name = 'version';
- start with 條件1
- connect by 條件2
- prior表示上一條記錄 好比 CONNECT BY PRIOR org_id = parent_id;就是說上一條記錄的org_id 是本條記錄的parent_id,
給一張圖 解釋
修改字符集
su - oracle
sqlplus /nolog
connect /as sysdba
--查看數據庫字符編碼集
select userenv('language') from dual;
shutdown immediate
startup restrict
alter database character set INTERNAL_USE ZHS16GBK;
shutdown immediate
startup
複製代碼
1. 取得每一個部門中最高薪水的人員名稱
SELECT
f.DEPTNO,
f.DNAME,
f.ENAME,
MAX(f.SAL) AS maxsal
FROM
(
SELECT
d.DEPTNO,
d.DNAME,
e.ENAME,
e.SAL
FROM
dept d
JOIN emp e ON e.DEPTNO = d.DEPTNO
) f
GROUP BY
f.DNAME
+--------+------------+-------+---------+
| DEPTNO | DNAME | ENAME | maxsal |
+--------+------------+-------+---------+
| 10 | ACCOUNTING | KING | 5000.00 |
| 20 | RESEARCH | SMITH | 3000.00 |
| 30 | SALES | ALLEN | 2850.00 |
+--------+------------+-------+---------+
2. 查詢出哪些人的薪水在平均薪水之上
分析: 1.咱們要先找出每一個部門的平均薪水,而後跟咱們的emp表進行鏈接誒,比較薪水大於平均薪水的
SELECT
d.ename,
d.sal,
d.deptno,
f.avgsal
FROM
emp d
JOIN (
SELECT
e.DEPTNO,
AVG(e.sal) AS avgsal
FROM
emp e
GROUP BY
e.DEPTNO
) f ON f.DEPTNO = d.deptno
WHERE
d.sal > f.avgsal
+-------+---------+--------+-------------+
| ename | sal | deptno | avgsal |
+-------+---------+--------+-------------+
| ALLEN | 1600.00 | 30 | 1566.666667 |
| JONES | 2975.00 | 20 | 2220.833333 |
| BLAKE | 2850.00 | 30 | 1566.666667 |
| CLARK | 2450.00 | 20 | 2220.833333 |
| SCOTT | 3000.00 | 20 | 2220.833333 |
| KING | 5000.00 | 10 | 3150.000000 |
| FORD | 3000.00 | 20 | 2220.833333 |
+-------+---------+--------+-------------+
3. 取出部門中的人的平均薪水等級
思路先求出每一個人的薪水等級,而後根據此表分組,計算出平均值, 而後根據dept表查詢出部門
SELECT
h.deptno,
d.dname,
h.avggra
FROM
dept d
JOIN (
SELECT
f.deptno,
AVG(f.grade) AS avggra
FROM
(
SELECT
e.ename,
e.deptno,
s.grade
FROM
emp e
JOIN salgrade s ON e.sal BETWEEN s.losal AND s.hisal
) f
GROUP BY
f.deptno
) h
ON
h.deptno = d.deptno
或者
SELECT
f.deptno,
d.dname,
AVG(f.grade) AS avggra
FROM
(
SELECT
e.ename,
e.deptno,
s.grade
FROM
emp e
JOIN salgrade s ON e.sal BETWEEN s.losal AND s.hisal
) f
JOIN dept d ON d.deptno = f.deptno
GROUP BY
f.deptno
+--------+------------+--------+
| deptno | dname | avggra |
+--------+------------+--------+
| 10 | ACCOUNTING | 3.5000 |
| 20 | RESEARCH | 3.0000 |
| 30 | SALES | 2.5000 |
+--------+------------+--------+
或者 是 查詢出平均薪水 而後根據 平均薪水找對應等級
SELECT
f.deptno,
d.dname,
s.grade,
f.avgsal
FROM
salgrade s
JOIN (
SELECT
e.ename,
e.deptno,
AVG(e.sal) AS avgsal
FROM
emp e
GROUP BY
e.deptno
) f ON f.avgsal BETWEEN s.losal AND s.hisal
JOIN dept d ON f.deptno = d.deptno
+--------+------------+-------+
| deptno | dname | grade |
+--------+------------+-------+
| 30 | SALES | 3 |
| 20 | RESEARCH | 4 |
| 10 | ACCOUNTING | 5 |
+--------+------------+-------+
4. 不許用max聚合函數,取得最高薪水等級 給出兩種方案
SELECT
sal
FROM
emp
ORDER BY
sal DESC
LIMIT 1
+---------+
| sal |
+---------+
| 5000.00 |
+---------+
第二種方案 就是 兩個同樣的表比較 好比 (1,2,3,4),(1,2,3,4) 我要找出a表中小於b表中的數(1,2,3) 因此此時空掉的是 4 這個數字
SELECT
sal
FROM
emp
WHERE
sal NOT IN (
SELECT DISTINCT
a.sal
FROM
emp a
JOIN emp b ON a.sal < b.sal
)
+---------+
| sal |
+---------+
| 5000.00 |
+---------+
5.取出平均薪水最高的部門編號
SELECT
deptno,
avg(sal) AS avgsal
FROM
emp
GROUP BY
deptno
HAVING
avgsal = (
SELECT
max(a.avgsal) AS maxavg
FROM
(
SELECT
deptno,
avg(sal) AS avgsal
FROM
emp
GROUP BY
deptno
) a
)
6.找出平均薪水最高的部門所對應的部門名稱
SELECT
e.deptno,
d.dname,
avg(e.sal) AS avgsal
FROM
emp e
JOIN dept d
ON e.deptno=d.deptno
GROUP BY
e.deptno
HAVING
avgsal = (
SELECT
max(a.avgsal) AS maxavg
FROM
(
SELECT
deptno,
avg(sal) AS avgsal
FROM
emp
GROUP BY
deptno
) a
)
複製代碼
DROP TABLE IF EXISTS EMP;
DROP TABLE IF EXISTS DEPT;
DROP TABLE IF EXISTS SALGRADE;
CREATE TABLE DEPT
(DEPTNO int(2) not null ,
DNAME VARCHAR(14) ,
LOC VARCHAR(13) ,
primary key (DEPTNO)
);
CREATE TABLE EMP
(EMPNO int(4) not null ,
ENAME VARCHAR(10) ,
JOB VARCHAR(9) ,
MGR INT(4) ,
HIREDATE DATE DEFAULT NULL ,
SAL DOUBLE(7,2) ,
COMM DOUBLE(7,2) ,
primary key (EMPNO) ,
DEPTNO INT(2)
);
CREATE TABLE SALGRADE
(GRADE INT ,
LOSAL INT ,
HISAL INT
);
INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES (
10, 'ACCOUNTING', 'NEW YOURK');
INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES (
20, 'RESEARCH', 'DALLAS');
INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES (
30, 'SALES', 'CHICAGO');
INSERT INTO DEPT( DEPTNO, DNAME, LOC ) VALUES (
40, 'OPERATIONS', 'BOSTON');
commit;
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7396, 'SMITH', 'CLERK', 7902, '1980-12-17', 800, NULL, 20);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7499, 'ALLEN', 'SALESMAN', 7698, '1981-02-20', 1600, 300,30);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7521, 'WARD', 'SALESMAN', 7698, '1981-02-22', 1250, 500, 30);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7566, 'JONES', 'MANAGER', 7839, '1981-04-02', 2975, NULL, 20);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7654, 'MARTIN', 'SALESMAN', 7698, '1981-09-28', 1250, 1400, 30);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7698, 'BLAKE', 'MANAGER', 7839, '1981-05-01', 2850, NULL, 30);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7782, 'CLARK', 'MANAGER', 7839, '1981-06-09', 2450, NULL, 20);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7788, 'SCOTT', 'ANALYST', 7566, '1987-04-19', 3000, NULL, 20);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7839, 'KING', 'PRESIDENT', NULL, '1981-11-17', 5000, NULL, 10);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7844, 'TURNER', 'SALESMAN', 7698, '1981-09-08', 1500, 0, 30);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7876, 'ADAMS', 'CLERK', 7788, '1987-05-23', 1100, NULL, 20);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7900, 'JAMES', 'CLERK', 7698, '1981-12-03', 950, NULL, 30);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7902, 'FORD', 'ANALYST', 7566, '1981-12-03', 3000, NULL, 20);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7934, 'MILLER', 'CLERK', 7782, '1982-01-23', 1300, NULL, 10);
commit;
INSERT INTO SALGRADE (GRADE, LOSAL, HISAL) VALUES (
1, 700, 1200);
INSERT INTO SALGRADE (GRADE, LOSAL, HISAL) VALUES (
2, 1201, 1400);
INSERT INTO SALGRADE (GRADE, LOSAL, HISAL) VALUES (
3, 1401, 2000);
INSERT INTO SALGRADE (GRADE, LOSAL, HISAL) VALUES (
4, 2001, 3000);
INSERT INTO SALGRADE (GRADE, LOSAL, HISAL) VALUES (
5, 3001, 9999);
commit;
複製代碼