日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

一条标准SQL语句是怎么执行之“步步惊心”过程详解与案例分析

發(fā)布時間:2024/9/27 数据库 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一条标准SQL语句是怎么执行之“步步惊心”过程详解与案例分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

SQL邏輯執(zhí)行過程詳解(限標準SQL)

表與數(shù)據(jù)

-- 1 創(chuàng)建 HR.Employees表 CREATE TABLE HR.Employees (empid INT NOT NULL IDENTITY,lastname NVARCHAR(20) NOT NULL,firstname NVARCHAR(10) NOT NULL,title NVARCHAR(30) NOT NULL,titleofcourtesy NVARCHAR(25) NOT NULL,birthdate DATE NOT NULL,hiredate DATE NOT NULL,address NVARCHAR(60) NOT NULL,city NVARCHAR(15) NOT NULL,region NVARCHAR(15) NULL,postalcode NVARCHAR(10) NULL,country NVARCHAR(15) NOT NULL,phone NVARCHAR(24) NOT NULL,mgrid INT NULL,CONSTRAINT PK_Employees PRIMARY KEY(empid),CONSTRAINT FK_Employees_Employees FOREIGN KEY(mgrid)REFERENCES HR.Employees(empid),CONSTRAINT CHK_birthdate CHECK(birthdate <= CAST(SYSDATETIME() AS DATE)) );CREATE NONCLUSTERED INDEX idx_nc_lastname ON HR.Employees(lastname); CREATE NONCLUSTERED INDEX idx_nc_postalcode ON HR.Employees(postalcode);-- 2 初始化數(shù)據(jù) SET IDENTITY_INSERT HR.Employees ON; INSERT INTO HR.Employees(empid, lastname, firstname, title, titleofcourtesy, birthdate, hiredate, address, city, region, postalcode, country, phone, mgrid)VALUES(1, N'Davis', N'Sara', N'CEO', N'Ms.', '19681208', '20130501', N'7890 - 20th Ave. E., Apt. 2A', N'Seattle', N'WA', N'10003', N'USA', N'(206) 555-0101', NULL); INSERT INTO HR.Employees(empid, lastname, firstname, title, titleofcourtesy, birthdate, hiredate, address, city, region, postalcode, country, phone, mgrid)VALUES(2, N'Funk', N'Don', N'Vice President, Sales', N'Dr.', '19720219', '20130814', N'9012 W. Capital Way', N'Tacoma', N'WA', N'10001', N'USA', N'(206) 555-0100', 1); INSERT INTO HR.Employees(empid, lastname, firstname, title, titleofcourtesy, birthdate, hiredate, address, city, region, postalcode, country, phone, mgrid)VALUES(3, N'Lew', N'Judy', N'Sales Manager', N'Ms.', '19830830', '20130401', N'2345 Moss Bay Blvd.', N'Kirkland', N'WA', N'10007', N'USA', N'(206) 555-0103', 2); INSERT INTO HR.Employees(empid, lastname, firstname, title, titleofcourtesy, birthdate, hiredate, address, city, region, postalcode, country, phone, mgrid)VALUES(4, N'Peled', N'Yael', N'Sales Representative', N'Mrs.', '19570919', '20140503', N'5678 Old Redmond Rd.', N'Redmond', N'WA', N'10009', N'USA', N'(206) 555-0104', 3); INSERT INTO HR.Employees(empid, lastname, firstname, title, titleofcourtesy, birthdate, hiredate, address, city, region, postalcode, country, phone, mgrid)VALUES(5, N'Mortensen', N'Sven', N'Sales Manager', N'Mr.', '19750304', '20141017', N'8901 Garrett Hill', N'London', NULL, N'10004', N'UK', N'(71) 234-5678', 2); INSERT INTO HR.Employees(empid, lastname, firstname, title, titleofcourtesy, birthdate, hiredate, address, city, region, postalcode, country, phone, mgrid)VALUES(6, N'Suurs', N'Paul', N'Sales Representative', N'Mr.', '19830702', '20141017', N'3456 Coventry House, Miner Rd.', N'London', NULL, N'10005', N'UK', N'(71) 345-6789', 5); INSERT INTO HR.Employees(empid, lastname, firstname, title, titleofcourtesy, birthdate, hiredate, address, city, region, postalcode, country, phone, mgrid)VALUES(7, N'King', N'Russell', N'Sales Representative', N'Mr.', '19800529', '20150102', N'6789 Edgeham Hollow, Winchester Way', N'London', NULL, N'10002', N'UK', N'(71) 123-4567', 5); INSERT INTO HR.Employees(empid, lastname, firstname, title, titleofcourtesy, birthdate, hiredate, address, city, region, postalcode, country, phone, mgrid)VALUES(8, N'Cameron', N'Maria', N'Sales Representative', N'Ms.', '19780109', '20150305', N'4567 - 11th Ave. N.E.', N'Seattle', N'WA', N'10006', N'USA', N'(206) 555-0102', 3); INSERT INTO HR.Employees(empid, lastname, firstname, title, titleofcourtesy, birthdate, hiredate, address, city, region, postalcode, country, phone, mgrid)VALUES(9, N'Doyle', N'Patricia', N'Sales Representative', N'Ms.', '19860127', '20151115', N'1234 Houndstooth Rd.', N'London', NULL, N'10008', N'UK', N'(71) 456-7890', 5); SET IDENTITY_INSERT HR.Employees OFF;

SQL實例

/* 要求:統(tǒng)計員工表里2014年1月1號及之后入職的員工所在國家、所屬年份、人數(shù), 過濾條件:以上信息里每個過國家和年份至少要對應有兩條記錄 排序:排序時按照國家和年份降序排列。 */ SELECT country, YEAR(hiredate) AS yearhired, COUNT(*) AS numemployees FROM HR.Employees WHERE hiredate >= '20140101' GROUP BY country, YEAR(hiredate) HAVING COUNT(*) > 1 ORDER BY country, yearhired DESC;

執(zhí)行過程

SQL不像程序語言順序去執(zhí)行代碼,它有自己的執(zhí)行順序。一般我們先從表和視圖開始,然后是記錄的WHERE過濾,再是分組和分組過濾,然后是SELECT列表,最后是ORDER BY排序。即對應:

  • ??? FROM
  • ??? WHERE
  • ??? GROUP BY
  • ??? HAVING
  • ??? SELECT
  • ??? ORDER BY
  • 特別的:

    如果在Mysql里,我們可以在GROUP BY、ORDER BY、HAVING之后引用SELECT里的字段別名。即如下的代碼是可運行的:

    SELECT deptno dpt,COUNT(empno) cnt FROM emp WHERE deptno IN(10,20) GROUP BY dpt HAVING cnt > 1/* 結果 dpt cnt 10 3 20 5 */

    過程分解

    1 FROM

    Step1: 首先鎖定FROM后的表HR.Employees,此時的員工表有9條記錄:

    2 WHERE

    Step2:接著通過WHERE關鍵字去Filter(過濾或者篩選) hiredate(入職時間)晚于2014年1月1日的記錄。這里用到到了算數(shù)表達式“≥”(大于等于)。因為針對時間類型,如果我們給的是字符串并且它是時間格式的。比如:20140101、2014-01-01、2014/01/01等,那么數(shù)據(jù)庫會將該字符串飲隱式(自動)轉成時間類型以進行時間的比較。所以過濾后的結果為:

    初學時我們會犯如下的錯誤:

    即在WHERE后直接用SELECT里字段的別名,如:

    SELECT country, YEAR(hiredate) AS yearhired FROM HR.Employees WHERE yearhired >= 2014;

    這顯然是錯誤,那是因為當前還沒有執(zhí)行到SELECT環(huán)節(jié),所以不知道別名yearhired。

    3 GROUP BY

    Step3:然后我們開始做分組了,這里要使用個函數(shù)Year來取hiredate(入職時間)里的年份。我們知道日期類型有“年月日”構成,當前需求是按照年這個維度進行統(tǒng)計,所以需要使用這個函數(shù),而country(國家)字段我們放在GROUP BY之后即可。分組之后的數(shù)據(jù)長這樣:

    4 HAVING

    Step4:通過觀察Step3里的結果我們返現(xiàn)國家是USA、年份是2014、2015的兩類數(shù)據(jù),每類只有1條,也就是說2014年、USA僅有1人入職;2015年、USA僅有1人入職,這個不是想要的,需求是每個分(類)組數(shù)據(jù)至少得有2條。這種對分組進行過濾的關鍵字就是HAVING,所以我們加上語句HAVING(COUNT(*))>1,即每個分類(組)的個數(shù)得是1以上。此時的結果長這樣:?

    5 SELECT

    Step5:目前Step4里的字段較多,而我們只想要COUNTRY(國家)、yearhired(年份)、numemployees(員工數(shù)),所以我們在結果集的返回列表里通過SELECT關鍵字往后依次寫上這些字段(列)或者這些字段相關的函數(shù),那么此時的結果為:

    注:類似在WHERE里引用SELECT里的字段別名,在SELECT環(huán)節(jié),我們同樣不能引用字段的別名。即如下寫法是報錯的:

    SELECT empid, country, YEAR(hiredate) AS yearhired, yearhired - 1 AS prevyear FROM HR.Employees;

    ??

    原因是SELECT后里的語句、字段、別名是在一個批次里執(zhí)行的,所以無法引用別名。但放在下一步的ORDER BY是可以的。

    6 ORDER BY

    Step6:結果和目標很接近了,再看看需求,我們需要對年份字段要按照逆序(降序)排列,即如果是數(shù)字、時間類型的,大的在前,小的在后;如果是字符串(以英文字母為例)類型的則z到a,反之正序(升序)則反過來。所以我們需要用到ORDER BY關鍵字,后跟字段或者字段的函數(shù)以及DESC(降序)、ASC(升序,可省略)來定義排序規(guī)則。所以得到最終結果:

    總結

    以上是生活随笔為你收集整理的一条标准SQL语句是怎么执行之“步步惊心”过程详解与案例分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。