筆記——《SQL從入門到提高》

來源:互聯網
上載者:User
本筆記整理了楊中科老師在傳智播客.Net培訓的《SQL從入門到提高》視頻講座。視頻相關連結:http://www.rupeng.com/forum/tj-16325-2477.html 資料庫相關概念   1、什麼是索引?優缺點是什嗎?索引是對資料庫表中一列或多列的值進行排序的一種單獨的、物理的資料庫結構。
   優點:
 1) 大大加快資料的檢索速度;
 2) 建立唯一性索引,保證資料庫表中每一行資料的唯一性;
 3) 加速表和表之間的串連;
 4) 在使用分組和排序子句進行資料檢索時,可以顯著減少查詢中分組和排序的時間。
   缺點:
 1) 索引需要佔物理空間;
 2) 當對錶中的資料進行增加、刪除和修改的時候,索引也要動態維護,降低了資料的維護速度。 2、業務主鍵和邏輯主鍵業務主鍵是使用有業務意義的欄位做主鍵,比如社會安全號碼,銀行帳號等;邏輯主鍵是使用沒有任何業務意義的欄位做主鍵。因為很難保證業務主鍵不會重複(社會安全號碼重複)、不會變化(帳號升位),因此推薦使用邏輯主鍵。 SQL Server 的使用   1、SQL Server 兩種常用的主鍵資料類型  1) int(或 bigint) + 識別欄位(又稱自動成長欄位)
     用識別欄位實現欄位自增可以避免並發等問題,不要開發人員控制自增。用識別欄位的欄位在Insert的時候不用指定主鍵的值。
     優點:佔用空間小、無需開發人員幹預、易讀;
     缺點:效率低,資料匯入匯出的時候很痛苦。
     設定:“修改表”->選定主鍵->“列屬性”->“標識規範”選擇“是”  2) uniqueidentifier(又稱GUID、UUID)
     GUID演算法是一種可以產生唯一表示的高效演算法,它使用網卡MAC、地址、納秒級時  間、晶片ID碼等算出來的,這樣保證每次產生的GUID永遠不會重複,無論是同一電腦還是不同電腦。在公元3400年前產生的GUID與任何其他產生過的GUID都不相同。SQL Server中產生GUID的函數newid()。
     優點:效率高、資料匯入匯出方便;
     缺點:佔用空間大、不易讀。  業界主流傾向於使用GUID。 SQL 基礎   1、DDL(資料定義語言 (Data Definition Language))    1) 建立資料表:
--建立表,SQL Server 的資料類型.CREATE TABLE T_Person(    Id int NOT NULL,     Name nvarchar(50),    Age int NULL,    PRIMARY KEY(Id));--建立表,添加外鍵.CREATE TABLE T_Users(    StudentNo CHAR(4),     CourseNo CHAR(4),    Score INT,    PRIMARY KEY(StudentNo),    FOREIGN KEY(CourseNo) REFERENCES T_Course(CourseNo));
  2) 修改表結構:
--修改表結構,添加欄位ALTER TABLE T_Person ADD NickName nvarchar(50) NULL;--修改表結構,刪除欄位ALTER TABLE T_Person DROP NickName;
  3) 刪除資料表:
DROP TABLE T_Person;
 4) 建立索引:
CREATE [UNIQUE] INDEX <索引名> ON <基本表名>(<列名序列>);
  2、DML(資料操縱語言)    1) 插入語句:
INSERT INTO T_Person(Id, Name, Age) VALUES(1, 'Jim', 20);
  2) 更新語句:
UPDATE T_Person SET Age=Age+1 where Name='tom' or Age<25;
  3) 刪除語句:
--刪除表中所有記錄.DELETE FROM T_Person;--刪除表中指定記錄.DELETE FROM T_Person WHERE Age>20;
  4) 查詢語句: 
--簡單的資料查詢.SELECT * FROM T_Employee;--只查詢需要的列.SELECT FNumber FROM T_Employee;--給列取別名.SELECT FNumber AS 編號, FName AS 姓名 FROM T_Employee;--使用 WHERE 查詢合格記錄.SELECT FName FROM T_Employee WHERE FSalary<5000;--對錶記錄進行排序.SELECT * FROM T_Employee ORDER BY FAge ASC,FSalary DESC;--ORDER BY 子句要放在 WHERE 子句之後.SELECT * FROM T_Employee WHERE FAge>23 ORDER BY FAge DESC,FSalary DESC;--WHERE 中可以使用的邏輯運算子:or、and、not、<、>、=、>=、<=、!=、<>等.--查詢不與任何錶關聯的資料.SELECT 1+1;SELECT newid();SELECT getdate();--模糊比對,首字母未知.SELECT * FROM T_Employee WHERE FName LIKE '_arry';--模糊比對,前後多個字元未知.SELECT * FROM T_Employee WHERE FName LIKE '%n%';--NULL 表示“不知道”,有 NULL 參與的運算結果一般都為 NULL.--查詢資料是否為 NULL,不能用 = 、!= 或 <>.SELECT * FROM T_Employee WHERE FName IS NULL;SELECT * FROM T_Employee WHERE FName IS NOT NULL;--查詢在某個範圍內的資料,IN 表示包含於.SELECT * FROM T_Employee WHERE FAge IN (23, 25, 28);--下面兩句等價。SELECT * FROM T_Employee WHERE FAge>=23 AND FAge<=30;SELECT * FROM T_Employee WHERE FAge BETWEEN 23 AND 30;
資料分組
--下面語句操作順序:先按年齡相同的進行分組,然後顯式每組年齡,並統計出每組行數.--注意:彙總函式是對分組操作結果進行運算.SELECT FAge,COUNT(*) FROM T_Employee GROUP BY FAge;--下面語句錯誤,因為一組中各行姓名 FName 是不同的,--不能使用沒有在 GROUP BY 中出現的欄位,彙總函式除外.SELECT FAge,FName,COUNT(*) FROM T_Employee GROUP BY FAge;--可以像下面這樣寫,因為一組中最大工資只有一個.SELECT FAge,MAX(FSalary),COUNT(*) FROM T_Employee GROUP BY FAge;--GROUP BY 應該放在 WHERE 的後面,彙總函式是不能出現在 WHERE 語句中的,--WHERE 是對原始表記錄進行條件操作,ORDER BY 是在條件操作之後進行分組操作,--HAVING 放在 ORDER BY 後面,用來對分組操作的結果集進行篩選操作,--HAVING 是 ORDER BY 的子句,不能代替 WHERE,HAVING 中的欄位必須出現在 GROUP BY 中.--下面語句操作順序:先按年齡相同的進行分組,然後篩選出行數大於 1 的分組。SELECT FAge,COUNT(*) FROM T_Employee     GROUP BY FAge        HAVING COUNT(*)>1;--下面語句是錯誤的,因為 FSalary 在每個分組中不是唯一的,不能用來標識分組.--HAVING能用的列和 SELECT 中能用的列是一樣的。SELECT FAge,COUNT(*) FROM T_Employee     GROUP BY FAge        HAVING FSalary>2000;
限制結果集
--限制結果集的行數:SELECT TOP 5 * FROM T_Employee ORDER BY FSalary DESC;--下面語句意圖:按照工資從高到低排序,檢索從第六名開始一共三個人的資訊。--操作順序:從內層到外層--先查詢倒序前五名的編號,然後排除前五名編號,--得到的資料從第六名開始,最後按倒序從第六名開始取前三名。SELECT TOP 3 * FROM T_Employee    WHERE FNumber NOT IN (        SELECT TOP 5 FNumber FROM T_Employee ORDER BY FSalary DESC)    ORDER BY FSalary DESC;--去除重複資料,所去除的是完全重複的記錄,即所有欄位都相同者去掉。--查詢所有員工的部門資訊,部門資訊重複.SELECT FDepartment FROM T_Employee;--想要查詢公司包含多少個部門,結果集中部門資訊重複,加關鍵字 DISTINCT 可以消除重複。SELECT DISTINCT FDepartment FROM T_Employee;
聯合結果集
--把 UNION 前後的查詢結果集合為一個結果集,返回的結果欄位數必須相同,各欄位類型必須相容。--預設情況下聯合結果集會自動去除重複。如果不想去除重複資料,需要在 UNION 後加上 ALL。SELECT FName,FAge,'臨時工,無部門' FROM T_TempEmployeeUNIONSELECT FName,FAge,FDepartment FROM T_Employee;--不去除重複的聯合結果集.SELECT FName,FAge,'臨時工,無部門' FROM T_TempEmployeeUNION ALLSELECT FName,FAge,FDepartment FROM T_Employee;--使用聯合結果集做報表.SELECT '正式員工最高年齡',MAX(FAge) FROM T_EmployeeUNION ALLSELECT '正式員工最低年齡',MIN(FAge) FROM T_EmployeeUNION ALLSELECT '臨時工最高年齡',MAX(FAge) FROM T_TempEmployeeUNION ALLSELECT '臨時工最低年齡',MIN(FAge) FROM T_TempEmployee;--使用聯合結果集查詢所用員工工資合計.SELECT FNumber, FSalary FROM T_EmployeeUNIONSELECT '工資合計',SUM(FSalary) FROM T_Employee;
SQL Server 部分函數 1、數學函數ABS():求絕對值
CEILING():舍入到最大整數(上限)。CEILING(3.33)=4,CEILING(-3.33)=-3
FLOOR():舍入到最小整數(下限)。FLOOR(3.33)=3,FLOOR(-3.33)=-4
ROUND():四捨五入。舍入到“離我半徑最近的數”。ROUND(3.1415,3)=3.142 2、字串函數LEN():求字串長度。LEN('abc')=3
LOWER()、UPPER():轉小寫、大寫
LTRIM():去掉字串左側空格
RTRIM():去掉字串右側空格
SUBSTRING(string,start_position,length):取子串,參數 string 為主字串,start_position 為子字串在主字串中的起始位置,length 為子字串的最大長度。 3、日期函數GETDATE():取當前日期時間
DATEADD(datepart,number,date):計算增加以後的日期。參數 date 為待計算的日期,參數 datepart 為計量單位(YEAR,YY,MONTH,MM,DAY,DD 等)DATEADD(DAY,3,date)為計算日期 date 的 3 天后的日期,DATEADD(MONTH,-8,date)為計算日期 date 的 8 個月前的日期
DATEDIFF(datepart,startdate,enddate):計算兩個日期之間的差額。datepart 為計量單位
DATEPART(datepart,date):返回一個日期的特定的部分
--查詢員工入職年數.SELECT FName,FInDate,DATEDIFF(YEAR,FInDate,GETDATE()) FROM T_Employee;--查詢各入職年數的員工個數.SELECT DATEDIFF(YEAR,FInDate,GETDATE()),COUNT(*) FROM T_Employee    GROUP BY DATEDIFF(YEAR,FInDate,GETDATE());
4、類型轉換函式CAST(expression AS date_type)
CONVERT(date_type,expression)
--字串轉換為整數SELECT CAST('123' AS INTEGER);--字串轉換成日期時間類型SELECT CAST('2008-08-08' AS DATETIME), CONVERT(DATETIME,'2008-08-08');SELECT DATEPART(YEAR,CAST('2008-08-08' AS DATETIME));--數字轉換成字串SELECT CONVERT(varchar(50),123);SELECT FIdNumber,    RIGHT(FIdNumber,3) AS 後三位,    CAST(RIGHT(FIdNumber,3) AS INTEGER) AS 後三位的整數形式,    CAST(RIGHT(FIdNumber,3) AS INTEGER)+1 AS 後三位加一,    CONVERT(INTEGER,RIGHT(FIdNumber,3))/2 AS 後三位除以2    FROM T_Person;
5、空值處理函數ISNULL(expression,value):如果 expression 不為空白則返回 expression,否則返回 value
--當記錄中 FName 欄位為 NULL 時顯式“佚名”SELECT ISNULL(FName,'佚名') AS 姓名 FROM T_Employee;
5、流量控制函數單值判斷,相當於 switch-case
CASE expression
WHEN value1 THEN return_value1
WHEN value2 THEN return_value2
WHEN value3 THEN return_value3
ELSE default_return_value
END
SELECT FName,(    CASE FLevel    WHEN 1 THEN 'VIP客戶'    WHEN 2 THEN '進階客戶'    WHEN 3 THEN '普通客戶'    ELSE '客戶類型錯誤'    END) AS FLevelName    FROM T_Customer;--範圍判斷SELECT FName,(    CASE    WHEN FSalary<2000 THEN '低收入'    WHEN FSalary>=2000 AND FSalary<=5000 THEN '中等收入'      ELSE '高收入'    END)    FROM T_Employee;
練習
--有一張表T_Scroes,記錄比賽成績:--Date       Name   Scroe--2008-8-8   拜仁   勝--2008-8-9   奇才   勝--2008-8-8   湖人   勝--2008-8-10  拜仁   負--2008-8-8   拜仁   負--2008-8-12  奇才   勝--要求輸出下面格式:--Name  勝  負--拜仁  1   2--湖人  1   0--奇才  2   0--注意:在中文字串前加 N,比如 N'勝'--下面運算順序:--先執行內層查詢,得到如下中間結果集:--Name   勝  負--拜仁   1   0--奇才   1   0--湖人   1   0--拜仁   0   1--拜仁   0   1--奇才   1   0--然後對中間結果集按隊名 Name 進行分組,最後計算出每組“勝”欄位的和與“負”欄位的和。SELECT Name,    SUM       (CASE Score        WHEN N'勝' THEN 1        ELSE 0        END) AS 勝,    SUM       (CASE Score        WHEN N'負' THEN 1        ELSE 0        END) AS 負    FROM T_Scroes    GROUP BY Name;
--建立一張表T_Callers,記錄撥打電話員的工作流程水,記錄呼叫員編號、對方號碼、通話開始時間、通話結束時間。建表、插資料等最後都自己寫SQL語句。--要求:--    1) 輸出所有資料中通話時間最長的5條記錄。--    2) 輸出所有資料中撥打長途號碼(對方號碼以0開頭)的總時間長度。--    3) 輸出本月通話總時間長度最多的前三個呼叫員的編號。--    4) 輸出本月撥打到電話次數最多的前三個呼叫員的編號。--    5) 輸出所有資料的撥號流水,並且在最後一行添加總呼叫時間長度。--          記錄呼叫員編號、對方號碼、通話時間長度--          ......--          匯總[市內號碼總時間長度][長途號碼總時間長度]--Id   CallerNumber   TellNumber    StartDateTime     EndDateTime--1    001            02088888888   2010-7-10 10:01   2010-7-10 10:05--2    001            02088888888   2010-7-11 13:41   2010-7-11 13:52--3    001            89898989      2010-7-11 14:42   2010-7-11 14:49  --4    002            02188368981   2010-7-13 21:04   2010-7-13 21:18--5    002            76767676      2010-6-29 20:15   2010-6-29 20:30--6    001            02288878243   2010-7-15 13:40   2010-7-15 13:56--7    003            67254686      2010-7-13 11:06   2010-7-13 11:19--8    003            86231445      2010-6-19 19:19   2010-6-19 19:25--9    001            87422368      2010-6-19 19:25   2010-6-19 19:36--10   004            40045862245   2010-6-19 19:50   2010-6-19 19:59--建立資料表T_Callers.CREATE TABLE T_Callers   (Id int NOT NULL,    CallerNumber varchar(3),    TellNumber varchar(13),    StartDateTime datetime,    EndDateTime datetime,    PRIMARY KEY(Id));--插入資料.INSERT INTO T_Callers(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime)    VALUES (1,'001','02088888888','2010-7-10 10:01','2010-7-10 10:05');INSERT INTO T_Callers(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime)    VALUES (2,'002','02088888888', '2010-7-11 13:41','2010-7-11 13:52');INSERT INTO T_Callers(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime)    VALUES (3,'003','89898989',      '2010-7-11 14:42',   '2010-7-11 14:49');INSERT INTO T_Callers(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime)    VALUES (4,'004','02188368981',   '2010-7-13 21:04',   '2010-7-13 21:18');INSERT INTO T_Callers(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime)    VALUES (5,'005','76767676',      '2010-6-29 20:15',   '2010-6-29 20:30');INSERT INTO T_Callers(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime)    VALUES (6,'006','02288878243',   '2010-7-15 13:40',   '2010-7-15 13:56');INSERT INTO T_Callers(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime)    VALUES (7,'007','67254686',      '2010-7-13 11:06',   '2010-7-13 11:19');INSERT INTO T_Callers(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime)    VALUES (8,'008','86231445',      '2010-6-19 19:19',   '2010-6-19 19:25');INSERT INTO T_Callers(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime)    VALUES (9,'009','87422368',      '2010-6-19 19:25',   '2010-6-19 19:36');INSERT INTO T_Callers(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime)    VALUES (10,'010','40045862245',   '2010-6-19 19:50',   '2010-6-19 19:59');--修改呼叫員編號.UPDATE T_Callers SET CallerNumber='001' WHERE Id IN (1,2,3,6,9);UPDATE T_Callers SET CallerNumber='002' WHERE Id IN (4,5);UPDATE T_Callers SET CallerNumber='003' WHERE Id IN (7,8);UPDATE T_Callers SET CallerNumber='004' WHERE Id=10;--題 1):--@計算通話時間;--@按通話時間降序排列;--@取前5條記錄。SELECT TOP 5 * FROM T_Callers     ORDER BY DATEDIFF(SECOND,StartDateTime,EndDateTime) DESC;--題 2):--@查詢撥打長途號碼的記錄;--@計算各撥打長途號碼的通話時間長度;--@對各撥打長途號碼的通話時間長度進行求和。SELECT SUM(DATEDIFF(SECOND,StartDateTime,EndDateTime)) AS 長途總時間長度     FROM T_Callers     WHERE TellNumber LIKE '0%';--題 3):輸出本月通話總時間長度最多的前三個呼叫員的編號.--@按呼叫員編號進行分組;--@計算各呼叫員通話總時間長度;--@按通話總時間長度進行降序排列;--@查詢前3條記錄中呼叫員的編號。SELECT TOP 3 CallerNumber FROM T_Callers     GROUP BY CallerNumber    ORDER BY SUM(DATEDIFF(SECOND,StartDateTime,EndDateTime)) DESC;--題 4) 輸出本月撥打到電話次數最多的前三個呼叫員的編號.--@按呼叫員編號進行分組;--@計算個呼叫員撥打到電話的次數;--@按呼叫員撥打到電話的次數進行降序排序;--@查詢前3條記錄中呼叫員的編號。SELECT TOP 3 CallerNumber FROM T_Callers     GROUP BY CallerNumber    ORDER BY COUNT(*) DESC;--題5) 輸出所有資料的撥號流水,並且在最後一行添加總呼叫時間長度:--        記錄呼叫員編號、對方號碼、通話時間長度--        ......--        匯總[市內號碼總時間長度][長途號碼總時間長度]--@計算每條記錄中通話時間長度;--@查詢包含不加 0 號碼,即市內號碼的記錄;--@計算市內號碼通話總時間長度;--@查詢包含加 0 號碼,即長途號碼的記錄;--@計算長途號碼通話總時間長度;--@聯集查詢。(SELECT     CallerNumber AS 呼叫員編號,    TellNumber AS 對方號碼,    DATEDIFF(SECOND,StartDateTime,EndDateTime) AS 通話時間長度    FROM T_Callers)UNION(SELECT     '匯總',    CAST(SUM(DATEDIFF(SECOND,StartDateTime,EndDateTime)) AS varchar),    CAST(       (SELECT            SUM(DATEDIFF(SECOND,StartDateTime,EndDateTime))            FROM T_Callers            WHERE TellNumber LIKE '0%')         AS varchar)    FROM T_Callers    WHERE TellNumber NOT LIKE '0%');--另一種查詢匯總的方法:SELECT '匯總',    SUM(        CASE        WHEN TellNumber NOT LIKE '0%'             THEN DATEDIFF(SECOND,StartDateTime,EndDateTime)        ELSE 0        END),    SUM(CASE        WHEN TellNumber LIKE '0%'             THEN DATEDIFF(SECOND,StartDateTime,EndDateTime)        ELSE 0        END)    FROM T_Callers;--題 1):輸出所有資料中通話時間最長的5條記錄.--@計算通話時間;--@按通話時間降序排列;--@取前5條記錄。SELECT TOP 5 * FROM T_Callers ORDER BY DATEDIFF(SECOND,StartDateTime,EndDateTime) DESC;--題 2):輸出所有資料中撥打長途號碼(對方號碼以0開頭)的總時間長度.--@查詢撥打長途號碼的結果集;--@計算各撥打長途號碼的通話時間長度;--@對各撥打長途號碼的通話時間長度進行求和。SELECT SUM(DATEDIFF(SECOND,StartDateTime,EndDateTime)) AS 長途總時間長度     FROM T_Callers     WHERE TellNumber LIKE '0%';--題 3):輸出本月通話總時間長度最多的前三個呼叫員的編號.--@按呼叫員編號進行分組;--@計算各呼叫員通話總時間長度;--@按通話總時間長度進行降序排列;--@查詢前3條記錄中呼叫員的編號。SELECT TOP 3 CallerNumber FROM T_Callers     GROUP BY CallerNumber    ORDER BY SUM(DATEDIFF(SECOND,StartDateTime,EndDateTime)) DESC;--題 4) 輸出本月撥打到電話次數最多的前三個呼叫員的編號.--@按呼叫員編號進行分組;--@計算個呼叫員撥打到電話的次數;--@按呼叫員撥打到電話的次數進行降序排序;--@查詢前3條記錄中呼叫員的編號。SELECT TOP 3 CallerNumber FROM T_Callers     GROUP BY CallerNumber    ORDER BY COUNT(*) DESC;--題5) 輸出所有資料的撥號流水,並且在最後一行添加總呼叫時間長度:--        記錄呼叫員編號、對方號碼、通話時間長度--        ......--        匯總[市內號碼總時間長度][長途號碼總時間長度]--@計算每條記錄中通話時間長度;--@查詢包含不加 0 號碼,即市內號碼的記錄;--@計算市內號碼通話總時間長度;--@查詢包含加 0 號碼,即長途號碼的記錄;--@計算長途號碼通話總時間長度;--@聯集查詢。(SELECT     CallerNumber AS 呼叫員編號,    TellNumber AS 對方號碼,    DATEDIFF(SECOND,StartDateTime,EndDateTime) AS 通話時間長度    FROM T_Callers)UNION(SELECT     '匯總',    CAST(SUM(DATEDIFF(SECOND,StartDateTime,EndDateTime)) AS varchar),    CAST(       (SELECT            SUM(DATEDIFF(SECOND,StartDateTime,EndDateTime))            FROM T_Callers            WHERE TellNumber LIKE '0%')         AS varchar)    FROM T_Callers    WHERE TellNumber NOT LIKE '0%');--另一種查詢匯總的方法:SELECT '匯總',    SUM(        CASE        WHEN TellNumber NOT LIKE '0%'             THEN DATEDIFF(SECOND,StartDateTime,EndDateTime)        ELSE 0        END),    SUM(CASE        WHEN TellNumber LIKE '0%'             THEN DATEDIFF(SECOND,StartDateTime,EndDateTime)        ELSE 0        END)    FROM T_Callers;

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.