1. 程式人生 > >內連線、外連線、子查詢(exists用法,關聯/非關聯子查詢)、課堂練習(行列轉換)、rownum和rowid

內連線、外連線、子查詢(exists用法,關聯/非關聯子查詢)、課堂練習(行列轉換)、rownum和rowid

笛卡爾積 和內連線 外連線

實際上是兩張表的乘積,查詢結果沒有實際意義
select * from emp,dept;

內連線-等值內連線(隱式)

select * from emp,dept where emp.deptno = dept.deptno;

內連線-不等值內連線
select * from emp,dept where emp.deptno <> dept.deptno;

內連線-顯式內連線 
select * from emp inner join dept on emp.deptno = dept.deptno;

多表查詢時,習慣性的去取別名,資料庫在後臺進行多表操作的時候也會自動起別名進行查詢。
select * from emp e,dept d where e.deptno = d.deptno;

自連線:自己連線自己
select * from emp e1,emp m1 where e1.mgr = m1.empno;

內連線查詢練習

-- 查詢員工編號,員工姓名,經理編號, 經理姓名
select e1.empno,e1.ename,e1.mgr,e2.ename
from emp e1,emp e2
where e1.mgr = e2.empno;

-- 查詢員工編號,員工姓名,員工的部門名稱,經理編號, 經理姓名
select e1.empno,e1.ename,d.dname,e1.mgr,e2.ename
from emp e1,emp e2,dept d
where e1.mgr = e2.empno and e1.deptno = d.deptno;

-- 查詢員工編號,員工姓名,員工的部門名稱,經理編號, 經理姓名,經理的部門名稱
select e1.empno,e1.ename,d1.dname,e1.mgr,e2.ename,d2.dname from emp e1,emp e2,dept d1,dept d2 where e1.mgr = e2.empno and e1.deptno = d1.deptno and e2.deptno = d2.deptno; //這裡是員工和經理兩個物件,分別查詢兩個物件的部門名稱,需要引入兩次部門表,因為員工和他的經理可能是在同一個部門,也可能在不同的不能,如果只引用一個部門表的話會丟失掉員工和經理在不同部門的資料 -- 查詢員工編號,員工姓名,員工的部門名稱,員工工資等級,經理編號, 經理姓名,經理的部門名稱
select e1.empno,e1.ename,d1.dname,s.grade,e1.mgr,e2.ename,d2.dname from emp e1,emp e2,dept d1,dept d2,salgrade s where e1.mgr = e2.empno and e1.deptno = d1.deptno and e2.deptno = d2.deptno and e1.sal between s.losal and s.hisal; -- 查詢員工編號,員工姓名,員工的部門名稱,員工工資等級,經理編號, 經理姓名,經理的部門名稱,經理工資等級 select e1.empno,e1.ename,d1.dname,s1.grade,e1.mgr,e2.ename,d2.dname,s2.grade from emp e1,emp e2,dept d1,dept d2,salgrade s1,salgrade s2 where e1.mgr = e2.empno and e1.deptno = d1.deptno and e2.deptno = d2.deptno and e1.sal between s1.losal and s1.hisal and e2.sal between s2.losal and s2.hisal; -- 查詢員工編號,員工姓名,員工的部門名稱,員工工資等級(一級),經理編號, 經理姓名,經理的部門名稱,經理工資等級 select e1.empno,e1.ename,d1.dname, case s1.grade when 1 then '一級' when 2 then '二級' when 3 then '三級' else '四級' end, e1.mgr,e2.ename,d2.dname, case s2.grade when 1 then '一級' when 2 then '二級' when 3 then '三級' when 4 then '四級' else '頂級' end from emp e1,emp e2,dept d1,dept d2,salgrade s1,salgrade s2 where e1.mgr = e2.empno and e1.deptno = d1.deptno and e2.deptno = d2.deptno and e1.sal between s1.losal and s1.hisal and e2.sal between s2.losal and s2.hisal;

外連線查詢練習

  • 左外連線: 查詢左表中所有的記錄,如果右表沒有對應的記錄,則顯示null
    left outer join .. on

select * from emp e left outer join dept d on e.deptno = d.deptno;

  • 右外連線: 查詢右表中所有的記錄,如果左表沒有對應的記錄,則顯示null
    right outer join .. on

select * from emp e right join dept d on e.deptno = d.deptno;

  • Oracle外連線特有寫法: (+) : 沒有對應的記錄, + null 值
  • 左外連線
    select * from emp e, dept d where e.deptno = d.deptno(+);

  • 右外連線
    select * from emp e,dept d where e.deptno(+) = d.deptno;

–擴充套件: oracle特有, 全外連線 – full join
select * from emp e full join dept d on e.deptno = d.deptno;

內連線和外連線的區別和關係:
這裡寫圖片描述

子查詢

概念: 查詢語句中巢狀查詢語句
作用: 用於解決複雜的查詢需求

分類:

單行子查詢
     查詢出來的結果只有一行
     常用操作符: > >= = < <= != <>
多行子查詢
     查詢出來的結果有多行
               常用的操作符: in , not in , any , all, exists,

查詢最高工資的員工資訊
select * from emp where sal = (select max(sal) from emp);

1)單行子查詢
子查詢出來的結果只有一行
常用操作符: > >= = < <= != <>

-- 查詢出 比 僱員7654的工資 高,同時 和7788從事相同工作 的員工資訊
select * from emp
where sal>(select sal from emp where empno = 7654)
      and job = (select job from emp where empno = 7788)
      and empno != 7788;

-- 查詢每個部門最低工資的員工資訊 和 他所在的部門資訊
select *
from emp e,dept d
where sal in(select min(sal) from emp group by deptno)
      and e.deptno = d.deptno
或
select * 
from 
       emp e1,
       (select deptno,min(sal) minsal from emp group by deptno) t1,
       dept d1
where 
       e1.deptno = t1.deptno 
       and e1.sal = t1.minsal
       and e1.deptno = d1.deptno;

2)多行子查詢

常用的操作符: in , not in , any , all, exists,

-- 查詢出比10號部門任意員工薪資高的員工資訊
select * from emp where sal > any(select sal from emp where deptno = 10)

-- 查詢出比10號部門所有員工薪資高的員工資訊
select * from emp where sal > all(select sal from emp where deptno = 10)

-- 查詢是領導的員工資訊
select * from emp where empno in (select mgr from emp where mgr is not null);
select * from emp where empno = any(select mgr from emp where mgr is not null);


-- 查詢不是領導的員工資訊   所有都滿足
select * from emp where empno not in(select mgr from emp where mgr is not null);
select * from emp where empno <>all(select mgr from emp where mgr is not null);

-- 注意: 子查詢中包含空值

3)exists用法
exists(查詢語句): 存在
如果查詢語句,有結果,則返回true,否則返回false ;
in和exists 是可以替換去使用,如果資料量小,使用in高效, 如果資料量大,用exists效率高一些

例子:下面兩條sql語句的查詢結果都是為空記錄
select * from emp where exists(select * from emp where empno=1234567);
select * from emp where 1=2;
下面兩條sql語句的查詢結果都是查詢出所有記錄
select * from emp where exists(select * from emp where empno=7369);
select * from emp where 1=1;

-- 查詢有員工的部門資訊
select * from dept where deptno in(select distinct deptno from emp);
select * from dept d where exists (select * from emp e where d.deptno = e.deptno);

4)關聯子查詢和非關聯子查詢
關聯子查詢: 子查詢依賴外層查詢,子查詢不能夠單獨執行
先執行外層查詢,然後再執行內層查詢
非關聯子查詢: 子查詢可以單獨執行,不依賴外層查詢條件,只查詢能夠單獨進行執行
先執行子查詢,再執行外層查詢,內層子查詢只執行一次
按照行劃分:
單行子查詢
多行子查詢
按照出現的位置劃分:
select
from 當作一張表處理,需要取別名
where
having

4.1)select 後面接子查詢

– 查詢員工姓名和部門名稱
select e.ename,d.dname from emp e,dept d where e.deptno = d.deptno;
select ename,(select dname from dept d where d.deptno=e.deptno) from emp e;

練習

1)練習一: 找到員工表中工資最高的前三名(只要前三條) — rownum

引入rownum的概念,rownum主要用在分頁查詢、查詢前多少名
注意:sql語句的執行順序如下:
from .. where … group by .. having .. select ..rownum.. order by
是先加入rownum,然後再進行order by的,所有這樣的話,如果存在排序的話,這樣的執行順序會讓rownum失效;所以需要先將把進行排序,然後再加入rownum這個量
另外,rownum值不能夠執行>這種條件的,查詢不出資料,因為rownum是再查詢出資料之後,才進行rownum的編號,預設起始從1開始;

select * from emp order by sal desc;
  rownum : 偽列 ,代表的是行號
              rownum 預設起始值是 1 ,每查詢出一條記錄, rownum++     
       rownum :主要運用在分頁查詢         

-- 查詢行號小於3的所有記錄
select rownum,emp.* from emp where rownum < 3;

select rownum,emp.* from emp where rownum >=1;

-- rownum沒有順序了
/*
   from .. where ... group by .. having .. select ..rownum.. order by
*/
select emp.* from emp order by sal desc;

select rownum,tt.* from (select emp.* from emp order by sal desc) tt;

-- 查詢工資最高的前三名
select rownum,tt.* from (select emp.* from emp order by sal desc) tt where rownum <=3;

2)練習二:找到員工表中薪水大於本部門平均薪水的員工
select * from emp e,(select avg(sal) avgsal,deptno from emp group by deptno) tt
where e.deptno = tt.deptno and e.sal > tt.avgsal;

-- 1.分組統計每個部門的平均薪水
select deptno , avg(sal) avgsal from emp group by deptno;
-- 2. 連線查詢結果
select * from emp e,(select deptno , avg(sal) avgsal from emp group by deptno) tt
where e.deptno = tt.deptno and e.sal > tt.avgsal;

3)練習三:統計每年入職員工的個數
select count(1),to_char(hiredate,’yyyy’) from emp group by to_char(hiredate,’yyyy’)

select hiredate from emp;

-- 只顯示年
select to_char(hiredate,'yyyy') from emp;

-- 分組統計每年入職個數
select to_char(hiredate,'yyyy') yy,count(1) cc from emp group by to_char(hiredate,'yyyy');

4)行列轉換 - 修改練習三中的行和列的顯示,使其反轉
-- 1. 先將1987豎起來
select case yy when '1987' then cc end 
from
(select to_char(hiredate,'yyyy') yy,count(1) cc from emp group by to_char(hiredate,'yyyy')) tt;


-- 2. 去除1987中空值
select sum(case yy when '1987' then cc end) "1987" 
from
(select to_char(hiredate,'yyyy') yy,count(1) cc from emp group by to_char(hiredate,'yyyy')) tt;

-- 3. 計算Total
select sum(cc) "TOTAL"
from
(select to_char(hiredate,'yyyy') yy,count(1) cc from emp group by to_char(hiredate,'yyyy')) tt;


-- 4. 合併1987和total

select sum(cc) "TOTAL",
    sum(case yy when '1987' then cc end) "1987" 
from
(select to_char(hiredate,'yyyy') yy,count(1) cc from emp group by to_char(hiredate,'yyyy')) tt;


-- 5. 最終結果
select sum(cc) "TOTAL",
       sum(case yy when '1987' then cc end) "1987",
       sum(case yy when '1980' then cc end) "1980", 
       sum(case yy when '1981' then cc end) "1981", 
       sum(case yy when '1982' then cc end) "1982"
from
       (select to_char(hiredate,'yyyy') yy,count(1) cc from emp group by to_char(hiredate,'yyyy')) tt;

rownum 和rowid

   rowid: 偽列,代表的每行記錄在磁碟中存放的真實的實體地址
   rowid,用在索引查詢

select rowid,emp.* from emp where deptno>20 order by sal;


-- 查詢第5-10條記錄
-- 1.查詢前10條記錄
select rownum line,emp.* from emp where rownum <=10;

-- 2. 查詢行號>=5的記錄
select * from (select rownum line,emp.* from emp where rownum <=10) tt where line >=5;

擴充套件: 華為的筆試題

create table pp(

    pname varchar2(20)          
);

insert into pp values('aaa');
insert into pp values('bbb');
insert into pp values('ccc');

-- 使用一條語句刪除表中重複的記錄, 只保留rowid最小的記錄 
select distinct * from pp;

select rowid,pname from pp;

-- 1.分組查詢出所有最小的rowid
select pname,min(rowid) from pp group by pname;

-- 2. 刪除rowid不在範圍內資料(效率比第二種要高)
delete from pp where rowid not in(select min(rowid) from pp group by pname);

select * from pp;

-- 第二種寫法:
delete from pp p1 where rowid > (select min(rowid) from pp p2 where p2.pname=p1.pname);

集合運算

 集合運算:
         並集 union,交集 intersect,差集minus
 union會預設去重並進行排序,而union all不去除重複的,不進行排序
 union和or的區別:如果用or需要要求在同一張表下面,而union可以在不同的表下面進行。

集合運算的注意事項
1)列 的數量要一致
補齊,需要補相同的型別
如果不足,可以用null補齊
2)列的型別需要保持一致
3)列的順序需要一致;

/*


     員工表 ,  經理表
       工資,婚否      工資,婚否

    所有員工的婚否
*/
-- 工資大於1500 或者 20號部門下的員工
select * from emp where sal > 1500;

select * from emp where deptno=20;

-- 並集
select * from emp where sal > 1500
union
select * from emp where deptno=20;

select * from emp where sal > 1500
union all
select * from emp where deptno=20;


-- 工資大於1500 並且 20號部門下的員工
select * from emp where sal > 1500
intersect
select * from emp where deptno=20;


-- 工資大於1500 並且不是20號部門下的員工
select * from emp where sal > 1500
minus
select * from emp where deptno=20;


select * from emp where sal > 1500 or deptno=20;

-- 集合運算注意事項
/*
   1.列的數量要一致
   2.列的型別要保持一致
   3.列的順序要一致

   如果不足,可以用null補齊
*/
select ename,sal from emp where sal > 1500
union
select ename,sal from emp where deptno=20;


select ename,sal from emp where sal > 1500
union
select ename,'a' from emp where deptno=20;

select ename,sal from emp where sal > 1500
union
select ename,null from emp where deptno=20;

相關推薦

連線連線查詢(exists用法關聯/關聯查詢)課堂練習行列轉換rownumrowid

笛卡爾積 和內連線 外連線 實際上是兩張表的乘積,查詢結果沒有實際意義 select * from emp,dept; 內連線-等值內連線(隱式) select * from emp,dept where emp.deptno = dept.deptno

09--MySQL自學教程:多表查詢之內連線連線以及【查詢

1.為什麼要拆表? 去除冗餘資料 2.表與表之間的關係 一對一 比如 人和身份證 QQ和QQ密碼 一對多(多對一) 比如:學生和成績的關係 多對多 比如:老師和學生的關係 3

oracle 連線連線自然連線交叉連線練習

oracle 內連線、外連線、自然連線、交叉連線練習 --查詢員工資訊 select * from emp; --查詢部門資訊 select * from dept; --需求:查詢員工姓名、薪資和所在部門名稱、部門編號 --1.使用交叉連線(笛卡爾積)14條記錄 select ename,sal,dn

知識點理解:MySQL連線連線的區別

1、內連線:等值連線、非等值連線、自連線 2、外連線:左連線、右連線 理解MySQL什麼時候該使用內連線、什麼時候該使用外連線? (本文例子,來自動力節點) 1、內連線:顯示薪水大於2000的員工資訊,並顯示所屬的部門名稱 select e.ename,e.sal,d.dna

SQL的四種連線-左連線連線連線連線

聯接條件可在FROM或WHERE子句中指定,建議在FROM子句中指定聯接條件。WHERE和HAVING子句也可以包含搜尋條件,以進一步篩選聯接條件所選的行。     聯接可分為以下幾類:     1、內聯接(典型的聯接運算,使用像 =  或 <> 之類的比較運算

資料庫中連線連線連線連線連線交叉連線的區別

內連線: 內聯接使用比較運算子根據每個表共有的列的值匹配兩個表中的行。利用內連線可獲取兩表的公共部分的記錄。 又細分為三種: 等值連線: 在連線條件中使用等於號(=)運算子比較被連線列的列值,其查詢結果中列出被連線表中的所有列,包括其中的重複列。 不等值連線: 在

圖解MySQL 連線連線連線連線連線

用兩個表(a_table、b_table),關聯欄位a_table.a_id和b_table.b_id來演示一下MySQL的內連線、外連線( 左(外)連線、右(外)連線、全(外)連線)。 MySQL版本:Server version: 5.6.31 MySQ

MySQL連線連線

一、內連線 關鍵字:inner join on   語句:select * from a_table a inner join b_table bon a.a_id = b.b_id;   組合兩個表中的記錄,返回關聯欄位

圖解MySQL 連線連線連線連線連線……太多了

用兩個表(a_table、b_table),關聯欄位a_table.a_id和b_table.b_id來演示一下MySQL的內連線、外連線( 左(外)連線、右(外)連線、全(外)連線)。 MySQL版本:Server version: 5.6.31 MySQL

MYSQL之左連線連線連線連線連線

資料庫:MYSQL 建表語句: DROP TABLE IF EXISTS a_table ; CREATE TABLE a_table ( a_hero_id int(11) DEFAULT NULL, a_hero_name varchar(1

深入理解SQL的四種連線-左連線連線連線連線

1、內聯接(典型的聯接運算,使用像 = 或 <> 之類的比較運算子)。包括相等聯接和自然聯接。 內聯接使用比較運算子根據每個表共有的列的值匹配兩個表中的行。例如,檢索 students和courses表中學生標識號相同的所有行。 2、外聯接。外聯接

詳解SQL的四種連線-左連線連線連線連線

1、內聯接(典型的聯接運算,使用像 =  或 <> 之類的比較運算子)。包括相等聯接和自然聯接。      內聯接使用比較運算子根據每個表共有的列的值匹配兩個表中的行。例如,檢索 students和courses表中學生標識號相同的所有行。        2、

sql多表操作-連線inner join連線left/right (out) join交叉連線

1 內連線、外連線和交叉連線的區別 內連線:匹配2個表中的相同欄位,沒有的不加入結果集。 外連線:匹配2個表中共有的欄位。分為3種: 左連線——以左邊的為基準,右表中沒有的(相同欄位值)為null; 右連線——以右邊的為基準,左表中沒有的為null;

【技術篇】SQL的四種連線-左連線連線連線連線

聯接條件可在FROM或WHERE子句中指定,建議在FROM子句中指定聯接條件。WHERE和HAVING子句也可以包含搜尋條件,以進一步篩選聯接條件所選的行。     聯接可分為以下幾類:     1、內聯接(典型的聯接運算,使用像 =  或 <> 之類的比較運算子)。包括相等聯接和自然聯接。  

連線連線連線的區別

舉例說明 假設您有兩個表,每個表只有一個列,表資料如下 A B - - 1 3 2 4 3 5 4 6 注意,(1,2)是A表唯一的,(3,4)是公共的,並且(5,6)是B表獨有的 內連線 內連線是A表的所有行交上B

SQL中的交叉連線(CROSS JOIN)連線(INNER JOIN)連線(OUTER JOIN)

1、交叉連線CROSS JOIN 如果不帶條件子句,交叉連線將會返回被連線的兩個表的笛卡爾積,返回結果的行數等於兩個錶行數的乘積; select  *from 表名 cross join  表名  on  條件表示式  2、內連線 INNER JOIN 內連線僅返回那些滿足連線條件的資料行。在內連線中,

SQL的連線分為三種:連線連線交叉連線

先給出兩張表:一、內連線:    內連線(INNER JOIN):有兩種,顯式的和隱式的,返回連線表中符合連線條件和查詢條件的資料行。(所謂的連結表就是資料庫在做查詢形成的中間表)。1、等值連線     概念:在連線條件中使用等於號(=)運算子,其查詢結果中列出被連線表中的所

資料庫中連線連線連線

內連線:把兩個表中資料對應的資料查出來  外連線:以某個表為基礎把對應資料查出來(全連線是以多個表為基礎) student表 no name 1 a 2 b 3 c 4 d grade表 no grade 1 90 2 98 3 95 內連線 inner join(查詢條件

[資料庫]連線連線連線連線連線連線

1 內連線: 它返回欄位ID(連線條件)同時存在於兩個表中的記錄,也就是說,僅當至少有一個同屬於兩表的行符合聯接條件時,內聯接才返回行,內聯接消除與另一個表中的任何行不匹配的行。(inner join或者join) 2 左連線: 左邊表全部行+右邊表相匹配

連線連線連線查詢

表1:teacher +----+--------+ | id | name   | +----+--------+ |  1 | 劉德華 | |  2 | 張學友 | |  4 | 黎明   | +----+--------+ 表2:student +----+-----