重點介紹數字函數、字符串函數、日期函數、類型轉換函數cast /convert、表連接join等基礎,並詳細講述一個綜合練習,以鞏固所學到的sql知識。
例子或代碼中用到的table,若涉及到匯總(二)的表,如有需要請查閱匯總(二)!
一. 數字函數
1.1 代碼
--絕對值:3.1415,3.1415 select abs(3.1415);
select abs(-3.1415); --舍入到最大整數:4,4,-3,-3 select ceiling(3.2); select ceiling(3.7); select ceiling(-3.2); select ceiling(-3.7); --舍入到最小整數:3,3,-4,-4 select floor(3.2); select floor(3.7); select floor(-3.2); select floor(-3.7); --四舍五入到“離半徑最近的數”、后面的3即保留三位小數:3.1410,3.1420,-3.1410,-3.1420 select round(3.1413,3);
select round(3.1418,3); select round(-3.1413,3); select round(-3.1418,3);
------------------------------------------------
博主經營一家發飾淘寶店,都是純手工制作哦,開業沖鑽,只為信譽!需要的親們可以光顧一下!謝謝大家的支持!
店名:
小魚尼莫手工飾品店
經營:
發飾、頭花、發夾、耳環等(手工制作)
網店:
http://shop117066935.taobao.com/
---------------------------------------------------------------------
繼續正題...
二. 字符串函數
2.1 代碼
select len('abcd'); --字符串長度:4 select lower('abcdEMN'); --轉小寫 select upper('abcdEMN'); --轉大寫 select ltrim(' ss '); --去左空格 select rtrim(' ss '); --去右空格 select rtrim(ltrim(' ss ')); --去左右空格 select substring('abcdef',3,3); --結果:cde;格式:substring(string,startIndex,length)
2.2 分析
substring(string,startIndex,length),startIndex為子字符串在住字符串中的起始位置,length為子字符串的最大長度
三.日期函數
3.1代碼
--當前時間 select getdate();
--分別獲取年/月/日
select DatePart(year,getdate()),DatePart(month,getdate()),DatePart(day,getdate()); --在當前日期運算。格式:DateAdd(datePart,number,date);注:可用hh,dd,mm,yy表示hour/day/month/year select DateAdd(hour,3,getdate()); --加三小時hour select DateAdd(day,3,getdate()); --三天day select DateAdd(month,3,getdate()); --三月month select DateAdd(year,3,getdate()); --三年year --日期差值 格式:DateDiff(datePart,startDate,endDate); select DateDiff(hh,getdate(),DateAdd(dd,3,getdate()));
3.2 分析
參考下面的例子
1)員工入職年限表 select FName, FInDate as 入職日期,DateDiff(year,FInDate,getdate()) as 入職年限 from T_Employee; 2)入職n年的人數統計表(FInDate為入職時間) select DateDiff(year,FInDate,getdate()) as 入職年限, count(*) as 入職人員數 from T_Employee group by DateDiff(year,FInDate,getdate()) 3)每年入職人數統計表 select DatePart(year,FInDate),count(*) from T_Employee group by DatePart(year,FInDate)
四. 類型轉換
4.1代碼
1) 類型轉換兩種方式: select cast('123'as int); select cast('2008-08-08' as datetime); select convert(datetime,'2009-09-09'); select convert(varchar(50),123); 2)注意: select '123'+1; --不好!有時會報錯 select cast('123' as int)+1; --最好轉化為同一類型再運算 select DatePart(year,'2008-8-8') --不好!有時會報錯 select DatePart(year,cast('2008-8-8' as datetime)) --最好轉化為同一類型再運算
4.2分析
注意使用cast、convert時候,需要考慮轉換前后類型是否可以匹配,如要select cast('aaa'as int)是肯定會報錯的
在"2)"中說到的情況還是應該注意,有些時候會出現錯誤!!!
五.case語句
5.1代碼:
--case函數:實現離散值的判斷 select FName, ( case FLevel --加上'判斷值' when 1 then'普通客戶' when 2 then'會員' when 3 then 'VIP' else '未知客戶關系' end )as 客戶類型 from T_Customer --case函數:實現值域的判斷 select FName,FSalary, ( case --不寫'判斷值' when FSalary<2000 then '低收入' when FSalary>=2000 and FSalary <5000 then '中收入' else '高收入' end )as 收入水平 from T_Employee
5.2 分析
1).上面方式分別針對離散值判斷、值域判斷;繼續參考下面的小例子
2).有一張表記錄了比賽成績,創建代碼已經給出(大家可以參考),根據該表,完成以下題目
--創建T_Scores
create table T_Scores(FName nvarchar(50) ,score nvarchar(50)) insert into T_Scores(FName,score)values('Tom','勝'); insert into T_Scores(FName,score)values('Tom','負'); insert into T_Scores(FName,score)values('Lucy','負'); insert into T_Scores(FName,score)values('Lucy','負'); insert into T_Scores(FName,score)values('Jerry','勝');
eg_1.輸出新表,如果勝為1,負為0
select FName, ( case score when N'勝' then 1 else 0 end )as '勝', ( case score when N'負' then 1 else 0 end )as '負' from T_Scores
eg_2.輸出格式(統計勝負)
FName 勝 負
Tom 1 1
Lucy 0 2
Jerry 1 0
select FName, sum( case score when N'勝' then 1 else 0 end )as '勝', sum( case score when N'負' then 1 else 0 end )as '負' from T_Scores group by FName
3).有一張表記錄了正負值(正表示收入,負表示指出),創建代碼已經給出(大家可以參考),根據該表,完成以下題目
--創建表 T_Order create table T_Order(FNumber varchar(50) not null,FAmount int not null); insert into T_Order (FNumber,FAmount)values('Rk1',10); insert into T_Order (FNumber,FAmount)values('Rk2',20); insert into T_Order (FNumber,FAmount)values('Rk3',-30); insert into T_Order (FNumber,FAmount)values('Rk4',-10);
統計出收支情況,字段為 單號 收入 支出
select FNumber as 單號, ( case when FAmount>0 then FAmount else 0 end )as 收入, ( case when FAmount<0 then abs(FAmount) else 0 end )as 支出 from T_Order
六. 表連接join...on
6.1 代碼:
--常規定義: select T_Orders.BillNo,T_Customers.name from T_Orders join T_Customers on T_Orders.CustomerId=T_Customers.Id; --可以定義如此,書寫更簡單: select o.BillNo as 訂單號,c.Name,c.Age from T_Orders as o join T_Customers as c on o.CustomerId=c.Id;
6.2分析
參考下方兩個定義的表格,實現下方要求的操作。
--T_Customers表創建 create table T_Customers( Id int not null, Name nvarchar(50) collate Chinese_PRC_CI_AS null, Age int null ); insert into T_Customers(Id,Name,Age)values(1,N'tom',10); insert into T_Customers(Id,Name,Age)values(2,N'jerry',15); insert into T_Customers(Id,Name,Age)values(3,N'john',22); insert into T_Customers(Id,Name,Age)values(4,N'lily',18); insert into T_Customers(Id,Name,Age)values(5,N'lucy',18); --T_Orders表創建 create table T_Orders( Id int not null, BillNo nvarchar(50) collate Chinese_PRC_CI_AS null, CustomerId int null --看做T_Customers表的外鍵(雖然實際關系並未建立)! ); insert into T_Orders(Id,BillNo,CustomerId)values(1,N'001',1); insert into T_Orders(Id,BillNo,CustomerId)values(2,N'002',1); insert into T_Orders(Id,BillNo,CustomerId)values(3,N'003',3); insert into T_Orders(Id,BillNo,CustomerId)values(4,N'004',2); insert into T_Orders(Id,BillNo,CustomerId)values(5,N'005',2); insert into T_Orders(Id,BillNo,CustomerId)values(6,N'006',5); insert into T_Orders(Id,BillNo,CustomerId)values(7,N'007',4); insert into T_Orders(Id,BillNo,CustomerId)values(8,N'008',5);
內容示意圖
要求及答案:
--顯示所有訂單號對應的姓名、年齡: select o.BillNo as 訂單號,c.Name,c.Age from T_Orders as o join T_Customers as c on o.CustomerId=c.Id; --顯示15歲以上顧客對應的訂單號、年齡、年齡: select o.BillNo,c.Name,c.Age from T_Orders as o join T_Customers as c on o.CustomerId=c.Id where c.Age>15 --顯示年齡大於‘平均年齡’的顧客的購買訂單: (涉及子查詢) select o.BillNo,c.Name,c.Age from T_Orders as o join T_Customers as c on o.CustomerId=c.Id where c.Age>(select avg(Age) from T_Customers)
七.綜合練習
創建一張表,記錄電話呼叫員的工作流水號、呼叫員編號、對方號碼、通話開始時間、通話結束時間、。
建表、插數據等要求自己寫SQL語句來完成。
要求:
1)輸出所有數據中通話時間最長的5條記錄。(分析:需要用到orderby/ datediff。)
--所有通話時長(第一步) select *, DateDiff(second,StartDateTime,EndDateTime) as '通話時長'from T_Call; --通話時間最長的5條記錄(第二步) select top 5* from T_Call order by DateDiff(second,StartDateTime,EndDateTime) Desc;
2)輸出所有數據中撥打長途號碼(以0開頭)的總時長(分析:需要用到like/ datediff /sum。)
--獲取長途號碼(第一步) select * from T_Call where TelNum like '0%'; --長途總時長: select'長途總時長:', sum(DateDiff(second,StartDateTime,EndDateTime)) from T_Call where TelNum like '0%';
3)輸出本月通話時長最多的前三位呼叫員的編號(分析:datediff / DatePart / sum/order by)
****假定當前時間為'2010-7-20' --分辨是否為當月,0為是,其他為否(第一步) select CallerNumber, TelNum,DateDiff(month,StartDateTime,convert(datetime,'2010-7-20')) as '當前月' from T_Call --取當月的數據(第二步) select * from T_Call where DatePart(month,StartDateTime)=DatePart(month,'2010-7-20') --本月通話總時長最多的前3個呼叫員的編號(第三步)
select top 3 CallerNumber from T_Call where DatePart(month,StartDateTime)=DatePart(month,'2010-7-20') group by CallerNumber order by sum(DateDiff(second,StartDateTime,EndDateTime)) Desc --按照總量排序
備注:當月判斷也可使用 where DateDiff(month,StartDateTime,convert(datetime,'2010-7-20'))=0
4)輸出本月撥打電話次數最多的前三位呼叫員的編號。(分析:group by/count/ order by)
--每個呼叫員撥打電話次數(第一步) select CallerNumber, count(*)from T_Call group by CallerNumber --當月(第二步) select CallerNumber, count(*)from T_Call where DateDiff(month,StartDateTime,convert(datetime,'2010-7-20'))=0 group by CallerNumber --本月撥打次數最多的前3個呼叫員的編號(第三步) select top 3 CallerNumber, count(*)as '撥打次數'from T_Call where DateDiff(month,StartDateTime,convert(datetime,'2010-7-20'))=0 group by CallerNumber order by count(*) Desc
5)輸出所有數據的撥號流水,並且在最后一行添加總呼叫時長,即
呼叫員編號 對方號碼 通話時長
... ... ...
匯總 市內號碼總時長 長途號碼總時長
--通話時長(第一步) select Id,CallerNumber,TelNum,datediff(second,StartDateTime,EndDateTime)as '通話時長(s)' from T_Call --長途判斷(第二步) select ( case when TelNum like '0%' then 0 else 1 end ) from T_Call --呼叫時長分析(第三步) select N'匯總',( case when TelNum not like '0%' then datediff(second,StartDateTime,EndDateTime) else 0 end ) as '市話',( case when TelNum like '0%' then datediff(second,StartDateTime,EndDateTime) else 0 end ) as '長途' from T_Call --呼叫員工編號/對方號碼/通話時長 union all 通話時長(市話/長途)(第四步) select CallerNumber,TelNum,datediff(second,StartDateTime,EndDateTime) as '通話時長' from T_Call union all --呼叫時長統計 select N'匯總', convert(varchar(50),sum( --類型轉換,否則溢出 case when TelNum not like '0%' then datediff(second,StartDateTime,EndDateTime) else 0 end )) as '市話',sum( case when TelNum like '0%' then datediff(second,StartDateTime,EndDateTime) else 0 end ) as '長途' from T_Call
店名:
小魚尼莫手工飾品店
經營:
發飾、頭花、發夾、耳環等(手工制作)
網店:
http://shop117066935.taobao.com/