SQL語句常用命令整理---多表查詢

多表查詢之關(guān)連查詢

多表數(shù)據(jù)連接查詢,簡稱連接查詢。本篇我們來一同學(xué)習(xí)多表連接查詢的相關(guān)用法,主要內(nèi)容有:

  1. 內(nèi)連接查詢
  2. 外連接查詢
  3. 查詢結(jié)果合并
  4. 子查詢

首先第一張表還是我們之前用到t_employee,我們在另外新建一個表t_dept(部門表)建表命令如下:

drop table if exists t_dept;
create table t_dept(
_id int primary key,
deptno int(11),
dname varchar(20),
loc varchar(50));

插入數(shù)據(jù):

insert into t_dept
(_id,deptno,dname,loc)
values
('1','10','ACCOUNTING','NEW YORK'),
('2','20','RESEARCH','DALLAS'),
('3','30','SALES','CHICAGO'),
('4','40','OPERATIONS','BOSTON');

笛卡爾積

select * from t_employee,t_dept;
  • 結(jié)果如下:
empno ename job mgr hiredate sal comm deptno _id deptno dname loc
7369 SMITH CLERK 7902 2011-03-12 800 null 20 1 10 ACCOUNTING NEW YORK
7369 SMITH CLERK 7902 2011-03-12 800 null 20 2 20 RESEARCH DALLAS
7369 SMITH CLERK 7902 2011-03-12 800 null 20 3 30 SALES CHICAGO
7369 SMITH CLERK 7902 2011-03-12 800 null 20 4 40 OPERATIONS BOSTON
7499 ALLEN SALESMAN 7698 2012-03-12 1600 300 30 1 10 ACCOUNTING NEW YORK
7499 ALLEN SALESMAN 7698 2012-03-12 1600 300 30 2 20 RESEARCH DALLAS
7499 ALLEN SALESMAN 7698 2012-03-12 1600 300 30 3 30 SALES CHICAGO
7499 ALLEN SALESMAN 7698 2012-03-12 1600 300 30 4 40 OPERATIONS BOSTON

從結(jié)果可以看出,兩張表中的每條記錄都進(jìn)行了重組,導(dǎo)致最終查詢結(jié)果的條數(shù)為兩張表中的記錄數(shù)的乘積,這樣的結(jié)果積在數(shù)學(xué)上稱為笛卡爾積。簡單比喻下就是所有可能的組合都進(jìn)行了組合。

內(nèi)連接(INNER JOIN)

使用比較運算符(包括=、>、<、<>、>=、<=、!>和!<)進(jìn)行表間的比較操作,查詢與連接條件相匹配的數(shù)據(jù)。

  • 特殊:自連接:查詢每個員工的姓名、職位和領(lǐng)導(dǎo)姓名
    方法1:
select t1.ename,t1.job,t2.ename 
from
      t_employee t1,
      t_employee t2 
where
        t1.mgr = t2.empno; 

方法2:

select t1.ename,t1.job,t2.ename
from t_employee t1
inner join t_employee t2 on t1.mgr = t2.empno;
  • 查詢每個員工的編號、姓名、職位、部門名稱和部門所在位置
select t1.empno,t1.ename,t1.job,t2.dname,t2.loc
from t_employee t1
inner join t_dept t2 on t1. deptno = t2.deptno;
---------------------------------- or ---------------------------------------------
select  t1.empno,t1.ename,t1.job,t2.dname,t2.loc
from t_employee t1,t_dept t2
where t1.deptno = t2.deptno;
  • 查詢每個員工的編號、姓名、基本工資、職位、領(lǐng)導(dǎo)姓名、部門名稱和部門所在位置
select t1.empno,t1.ename,t1.sal,t1.job,t2.ename as mgr_name,t3.dname,t3.loc
from t_employee t1
inner join t_employee t2 on t1.mgr = t2.empno
inner join t_dept t3 on t1.deptno = t3.deptno;
---------------------------------- or ---------------------------------------------
select t1.empno,t1.ename,t1.sal,t1.job,t2.ename as mgr_name,t3.dname,t3.loc
from t_employee t1,t_employee t2,t_dept t3
where t1.mgr = t2.empno and t1.deptno = t3.deptno;

外連接

外連接分為左連接(LEFT JOIN)或左外連接(LEFT OUTER JOIN)、右連接(RIGHT JOIN)或右外連接(RIGHT OUTER JOIN)、全連接(FULL JOIN)或全外連接(FULL OUTER JOIN)。我們就簡單的叫:左連接、右連接和全連接。

左外連接(left join)

返回左表中的所有行,如果左表中行在右表中沒有匹配行,則結(jié)果中右表中的列返回空值。

  • 查詢每個員工的姓名、職位和領(lǐng)導(dǎo)姓名
select t1.ename,t1.job,t2.ename as mgr_name
from t_employee t1
left join t_employee t2 on t1.mgr = t2.empno;

結(jié)果:

ename job mgr_name
SCOTT ANALYST JONES
KING PRESIDENT null

可以看到查詢結(jié)果的第二行,t2表無對應(yīng)匹配行,直接顯示為null,t1表所有值均顯示完全。專業(yè)一點說,即 左外連接 = 內(nèi)連接 + 左邊表內(nèi)連接之后剩余的其他記錄,右邊補(bǔ)NULL。

右外連接(right join)

恰與左連接相反,返回右表中的所有行,如果右表中行在左表中沒有匹配行,則結(jié)果中左表中的列返回空值。

  • 右外連接:查詢每個員工的編號、姓名、職位和部門名稱和部門位置
select t1.empno,t1.ename,t1.job,t2.dname,t2.loc
from t_employee t1
right join t_dept t2 on t1.deptno = t2.deptno;

結(jié)果:

empno ename job dname loc
7900 JAMES CLERK SALES CHICAGO
null null null OPERATIONS BOSTON

全連接(full join)

返回左表和右表中的所有行。當(dāng)某行在另一表中沒有匹配行,則另一表中的列返回空值
這里為了測試效果,插入一個不在在部門表搜索不到的員工記錄。如下:

insert into t_employee 
values
('7935','TEST','CLERK','7782','2011-03-12','1300',NULL,'50');
  • 查詢每個員工的編號、姓名、職位和部門名稱和部門位置
select t1.empno,t1.ename,t1.job,t2.dname,t2.loc
from t_employee t1
full join t_dept t2 on t1.deptno = t2.deptno;

......運行了一下發(fā)現(xiàn)MySQL并不支持全連接,但是可以通過其他途徑實現(xiàn)全連接的查詢結(jié)果。接下來我們學(xué)習(xí)的合并查詢記錄就可以實現(xiàn)我們想要的結(jié)果。

合并查詢數(shù)據(jù)記錄

合并查詢數(shù)據(jù)使用UNION或UNION ALL,思考一下全連接 = 左連接 UNION 右連接,趕快來試試

select t1.empno,t1.ename,t1.job,t2.dname,t2.loc
from t_employee t1
left join t_dept t2 on t1.deptno = t2.deptno
UNION
select t1.empno,t1.ename,t1.job,t2.dname,t2.loc
from t_employee t1
right join t_dept t2 on t1.deptno = t2.deptno;

結(jié)果:

empno ename job dname loc
7935 TEST CLERK NULL NULL
NULL NULL NULL OPERATIONS BOSTON

看下查詢結(jié)果,即是全連接的效果了。滿足了,我們再來看看UNION和UNION ALL的區(qū)別:

select t1.empno,t1.ename,t1.job,t2.dname,t2.loc
from t_employee t1
left join t_dept t2 on t1.deptno = t2.deptno
UNION ALL
select t1.empno,t1.ename,t1.job,t2.dname,t2.loc
from t_employee t1
right join t_dept t2 on t1.deptno = t2.deptno;

大家自行看查詢結(jié)果吧,區(qū)別還是很顯而易見的,即:
UNION執(zhí)行了去重的操作,而UNION ALL并沒有去重。


子查詢

子查詢說通俗一點,即是嵌套查詢??匆幌虏樵冋Z句,大家一下就明白了。

  • 查詢工資比SMITH還要高的全部員工的信息
select *
from t_employee t
where t.sal > (
           select sal
           from t_employee
           where ename = 'SMITH'); 

是不是已經(jīng)明白了,即是在上一次查詢結(jié)果的基礎(chǔ)上再做一次查詢。再練習(xí)一下。

  • 查詢工資和職位都與WARD一樣,并且不是WARD本人的員工的信息
SELECT
    *
FROM
    t_employee
WHERE
    (sal, job) = (
        SELECT
            sal,job
        FROM
            t_employee
        WHERE
            ename = 'WARD'
    )
AND ename != 'WARD';
  • 查詢員工表中的員工信息,要求員工的編號都在部門表中有記錄
SELECT
    *
FROM
    t_employee
WHERE
    deptno IN (SELECT deptno FROM t_dept);
  • 查詢員工表中的員工信息,要求員工的編號不在部門表中有記錄
select *
from t_employee
where deptno NOT IN (select deptno from t_dept);

以上就是整理常見查詢命令的使用方法,這里最后給大家留一道面試遇到的一道SQL題。題目如下:

_id name value
1 a 1
2 b 2
3 a 1
4 b 2
5 b 2

執(zhí)行一條SQL語句,刪除表內(nèi)的重復(fù)行。如下結(jié)果(*表示值不限定):

_id name value
* a 1
* b 2

大家可能會想到的解決辦法如下:

delete from t_test
where `_id` NOT IN (
          select min(id)
          from t_test
          group by `name`,`value`
          having count(*) > 1);

但是這樣會報這樣一個錯誤You can't specify target table 't_test' for update in FROM clause,查了Google這是因為MySQL不支持select語句與delete、update語句同時出現(xiàn)在同一個表中。在網(wǎng)上找到了解決辦法,非常巧妙的解決~將語句改成如下:

DELETE FROM
    t_test
WHERE
    `_id` NOT IN (
    select MIN(_id)
from (SELECT * from t_test) t
GROUP BY t.name,t.value
HAVING count(*) > 1
);

重點就在select min(_id) from (SELECT * from t_test) t,它將表的所有數(shù)據(jù)做成了一個子集,這樣就巧妙的解決了select語句與delete、update語句同時出現(xiàn)在同一個表中的問題了。很有啟發(fā)性~
以上兩篇即是關(guān)于SQL語句的學(xué)習(xí)。:)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容