題目:http://www.cnblogs.com/dunitian/p/6028838.htmlhtml
彙總:http://www.cnblogs.com/dunitian/p/5977425.htmlsql
說明:若有錯誤能夠批評指正,有更好寫法也能夠提點下~ 數據庫
1. 求結果:select "1"? 服務器
報錯,SQL裏面只有單引號,列如:'xx' 網絡
2. 查找包含"objs"的表?查找包含"o"的數據庫? 分佈式
select * from sys.objects where name like '%objs%' 函數
select * from sys.databases where name like '%o%' 性能
3. 求今天距離2002年有多少年,多少天? 測試
select datediff(yy,'2002',getdate()) 優化
select datediff(dd,'2002',getdate())
4. 請用一句SQL獲取最後更新的事務號(ID)
select top 1 ID from ServerUpdateTime order by LastUpdateDate desc
5. 有以下兩個表:
①請查詢11 ~ 15記錄的User
只是解題用:
select top 5 * from (select row_number() over(order by [User].UserID) ID,* from [User]) UserInfo
where UserInfo.ID>=11 and UserInfo.ID<=15
和子查詢的對比圖:
真正項目每每查詢User完整信息:
--其餘寫法
select * from
(
select top 5 * from (select row_number() over(order by [User].UserID) ID,* from [User]) UserInfo
where UserInfo.ID>=11 and UserInfo.ID<=15
) Temp
inner join User_Score on Temp.UserID=User_Score.UserID
--推薦寫法
select top 5 * from
(
select row_number() over(order by Temp.UserID) ID,* from
(
select [User].UserID,UserName,UserType,ScoreID,Score from [User]
inner join User_Score on [User].UserID=User_Score.UserID
)Temp
) UserInfo
where UserInfo.ID>=11 and UserInfo.ID<=15
依據:推薦寫法,看起來效率應該低點,但事實證實比其餘寫法效率高
②查詢用戶類型type=1總積分排名前十的user
select top 10 [User].* from [User]
inner join User_Score on [User].UserID=User_Score.UserID
where UserType=1
order by Score desc
③寫一條存儲過程,實現往User中插入一條記錄並返回當前UserId(自增加id)
--推薦寫法
if(Exists(select * from sys.objects where name=N'Usp_InsertedID'))
drop proc Usp_InsertedID
go
create proc Usp_InsertedID
as
insert into [User] output inserted.UserID values(N'張三蛋',3)
--另外一種寫法(SCOPE_IDENTITY()能夠獲得當前範圍內最近插入行生成的標示值)
if(Exists(select * from sys.objects where name=N'Usp_InsertedID'))
drop proc Usp_InsertedID
go
create proc Usp_InsertedID
as
insert into [User] values(N'李狗蛋',1)
select scope_Identity()
go
--不推薦:(@@Identity就不必定是當前範圍內了)
if(Exists(select * from sys.objects where name=N'Usp_InsertedID'))
drop proc Usp_InsertedID
go
create proc Usp_InsertedID
as
insert into [User] values(N'張三章',2)
select @@Identity
go
exec Usp_InsertedID
6. 請求出每一個班級的數學平均分,並按照高低進行排序
select avg(Score) AvgScore from Student
where Subject=N'數學'
group by Class
order by AvgScore desc
7. 一個TestDB表有A,B兩個字段。
①寫一句SQL求出有重複值的記錄。
--解題專用
select * from TestDB
where A in
(
select A from TestDB
group by A,B
having count(*)>1
)
order by A
--推薦:實際運用(真實環境下每每是爲了找出重複值而後假刪掉)
select * from
(
select row_number() over(partition by A,B order by A) ID,* from TestDB
) Temp
where Temp.ID>1
執行效率仍是有很大差距的,有圖有真相:
②請刪除重複項。(最好用兩種方法)
--傳統寫法:
select * into #Temp from (select distinct * from TestDB) A
drop table TestDB
select * into TestDB from #Temp
drop table #Temp
--推薦寫法(真正項目中基本上不會真刪)
delete Temp from (select row_number() over(partition by A,B order by A) ID,* from TestDB)Temp
where Temp.ID>1
8. 表中有A,B,C三列,用SQL實現:當A列>B列選擇A,不然選擇B,當B列>C列選擇B,不然選擇C
select
(
case
when A>B then A
else B
end
),
(
case
when B>C then B
else C
end
)from ABC
9. 數據行列互換
轉換前:
轉換後:
select Name,
sum(
case Courses
when '語文' then Score else 0
end
) 語文,
sum(
case Courses
when '數學' then Score else 0
end
)數學,
sum(
case Courses
when '物理' then Score else 0
end
)物理 from Student_Courses_Score
group by Name
10. 請統計每一個URL訪問次數,並按訪問次數由高到低的順序排序
select url,Count(*) n from WebUrl
group by url
order by n desc
順便打破一個僞結論:count(1)性能大於count(*)==》不要麻木相信優化,本身證明後再說~(PS:通常都是count(主鍵),有時候其餘狀況有大坑)
11. 用戶註冊表中id是自增加的。
①請查詢出一天24h每小時註冊的人數
select datepart(hh,CreateTime) '小時',count(*) '註冊人數' from User_Register
where CreateTime>=convert(varchar(10),getdate(),120) and CreateTime <convert(varchar(10),dateadd(day,1,getdate()),120)
group by datepart(hh,CreateTime)
②請查詢第4條記錄
select * from (select row_number() over(order by ID) RId,* from User_Register) Temp
where RId=4
③請查詢ID重複次數大於2次的記錄
--傳統方法(偏向於所有找出來)
select * from User_Register
where ID in
(
select ID from User_Register
group by ID having count(ID)>1
)
order by ID
--推薦方法(偏向於找多餘重複值)
select * from (select row_number() over(partition by ID order by ID) RId,* from User_Register) Temp
where RId>1
12. 圖書表(圖書號,圖書名,做者編號,出版社,出版日期)做者表(做者編號,做者姓名,年齡,性別)。用SQL語句查詢出年齡小於平均年齡的做者名稱、圖書名,出版社
select WriterName,BookName,PublishingHouse from Books
inner join Writer on Books.WriterNo=Writer.WriterNo
where Writer.Age < (select avg(Age) from Writer)
13. 返回num最小的記錄(禁止使用min,max等統計函數)
select top 1 * from TestNums
where num is not null
order by num
14. 舉例說下項目中視圖的好處?
項目裏面通常把一些業務比較複雜的東西封裝在一個視圖裏面,好比說項目裏面這個查詢用到了10多張表,表與表之間的關係邏輯你都得搞清楚,後期維護的時候又要拿出來弄懂,太浪費時間了,這時候視圖的做用就突襲出了
15. SQLServer有哪些系統數據庫?分別是幹什麼的?
Master,系統用的一些表、存儲過程
Tempdb,臨時表存放的數據庫
Msdb,定時任務存放的系統數據庫
Model,數據庫模版,新建數據庫的時候,他會把Model裏面的東西拷貝一份到新的數據庫裏面
eg:(其實不止這些系統表,這些是比較經常使用的)
16. 索引有什麼好處,又有何缺點?彙集索引和非彙集索引有什麼區別?
索引都是爲了提升查詢速度的,索引通常添加到不是頻繁改動的字段上。
索引也是佔空間滴,查詢速度是快了增刪改可就慢咯~
彙集索引影響排序,非彙集索引不影響排序。(主鍵默認是彙集索引哦)
彙集索引是主鍵時候的排序是這個樣子的:
彙集索引改爲Title01
默認排序就以Title01爲準了
17. 何時須要SQLServer發郵件?怎麼去發郵件(只要求掌握圖形化頁面,命令會使用便可)?
這個應用案例不少,通常都是預警,好比異常鏈接的時候,或者數據庫報錯的時候,通常都會和定時任務聯合使用。
發郵件相關介紹:http://www.cnblogs.com/dunitian/p/6022826.html
簡單說下:
在配置以前請先把郵件的POP3之類的設置一下:
圖形化演示:
配置名字隨意取,能夠用項目名。顯示名稱建議用版本號+服務器ip,這樣出問題能夠定位跟蹤
微軟圖形化的東西通常有個特色,一路下一步基本上能解決全部基礎問題
勾選一下(貌似不勾選也沒事)
測試一下:
發一封郵件到"我爲NET狂"的官方郵件去
去看看:
命令演示:(不須要記,你又不是DBA,會用便可)
發送郵件腳本:
1 |
exec msdb.dbo.sp_send_dbmail |
結果:20的ip也發過來了
--相關查詢
--select * from msdb.dbo.sysmail_allitems
--select * from msdb.dbo.sysmail_faileditems --失敗狀態的消息
--select * from msdb.dbo.sysmail_unsentitems --看未發送的消息
--select * from msdb.dbo.sysmail_sentitems --查看已發送的消息
--select * from msdb.dbo.sysmail_event_log --記錄日記
18. 存儲過程有什麼優勢?又有哪些缺點?
存儲過程執行效率高。1.傳輸的字節少響應也就快了嘛;2.存儲過程建立的時候已經預編譯好了,運行時直接進行執行計劃,而傳統的sql腳本得先生成執行計劃再執行。3.SQL注入防禦
擴展不方便,好比數據庫是複合的Nosql+MSSQL,代碼修改業務更方便。存儲過程裏面的SQL就不適合了(你SQLServer的腳本總不能和其餘NoSQL的通用吧),得抽出來用代碼實現。
19. 數據庫TestStudent中學生表用到了TestMain中的Class表。
①請查詢一下TestStudent中的學生在哪一個班級?
一個服務器,多個數據庫
--跨數據庫查詢
select SId,SName,CName from [TestStudent].[dbo].[StudentInfo] as Student
inner join [TestMain].[dbo].[Class] as Class on Student.SClassId=Class.CId
go
--多個服務器,多個數據庫
--先連接服務器
--跨數據庫查詢
select SId,SName,CName from [q***257691.my3w.com].[q***257691_db].[dbo].[StudentInfo] as Student
inner join [TestMain].[dbo].[Class] as Class on Student.SClassId=Class.CId
go
②思考一下要是我修改了TestMain的數據庫名如何避免再次去批量修改SQL?
一個服務器,多個數據庫
--要是我手動改了數據庫名或者表名豈不歇菜?全部就有了同義詞
use TestMain
if(exists(select * from sys.synonyms where name='TestMainClass'))
drop synonym TestMainClass
create synonym TestMainClass for [TestMain].[dbo].[Class]
if(exists(select * from sys.synonyms where name='TestStudentInfo'))
drop synonym TestStudentInfo
create synonym TestStudentInfo for [TestStudent].[dbo].[StudentInfo]
--跨數據庫查詢
use TestMain
select SId,SName,CName from TestStudentInfo as Student
inner join TestMainClass as Class on Student.SClassId=Class.CId
go
--多個服務器,多個數據庫
--先連接服務器,再同義詞
--要是我手動改了數據庫名或者表名豈不歇菜?全部就有了同義詞
use TestMain
if(exists(select * from sys.synonyms where name='TestMainClass'))
drop synonym TestMainClass
create synonym TestMainClass for [TestMain].[dbo].[Class]
if(exists(select * from sys.synonyms where name='TestStudentInfo'))
drop synonym TestStudentInfo
create synonym TestStudentInfo for [q***257691.my3w.com].[q***257691_db].[dbo].[StudentInfo]
--跨數據庫查詢
use TestMain
select SId,SName,CName from TestStudentInfo as Student
inner join TestMainClass as Class on Student.SClassId=Class.CId
go
20. 針對索引缺點,項目中咱們通常怎麼解決?
讀寫分離(發佈訂閱)
讀庫創建索引,寫庫不創建索引
簡單演示一下發布訂閱,具體的能夠自行研究:
發佈:
訂閱:
數據同步問題就不用你操心了
21. 隨着業務的發展,大家數據庫層面是怎麼逐步處理的?(我之前在羣裏也系統的說過,這個主要考察你是否真正參與一次頗具規模的完整項目中,不必定長篇大論,說你知道的就好了)
先聲明一些,若是有什麼錯誤歡迎反饋,畢竟這個下面的東西都是逆天本身慢慢摸索的,並無人指導,因此不免會出錯~~~(仍是先說下的好,否則有些不肯意分享的人會揪着小問題說啥誤人子弟。PS:逆天寧願別人也這樣誤誤我,本身搗鼓說出來都是淚啊!)
一開始是數據量慢慢大了查詢特別慢,因而在不常常修改又常用的列創建了索引,等差很少表裏有100w左右的數據了,開始有點吃不消了,因而就有了分表技術。分表技術不少,hashcode取餘,路由表等等。。。剛開始就是僞分表,也就是傳說中的水平分表,仍是在一個數據庫裏面,主要目的就是爲了解決ID溢出或者單個表數據太多而致使查詢太慢。
後來仍是有點吃不消,總不能由於某個表而影響總體性能吧,因而就把這個特別影響數據庫總體性能的表拎出來,放到另外的數據庫裏面,這個就是分庫技術,把一些影響總體性能的表單獨放到其餘數據庫裏面叫作垂直分庫,由於不在同一個數據庫了,也就能夠不放在一個盤裏面了,大大化解了IO的壓力。後來衍生出了垂直分表的概念(把某些分表放在其餘庫裏面,這時候路由表的表名就得寫全了)。
(擴:水平分庫:http://www.cnblogs.com/dunitian/p/5276431.html)
舉了個簡單的例子:
後來系統繼續用繼續用,發現...又不給力了,這時候是服務器瓶頸了(網絡,IO,鏈接數,CPU,內存等硬件瓶頸),這時候所謂的本機垂直分庫就意義不大了,就有了分佈式的概念,分佈式分佈式,也就是單機變成多機器嘛,這時候sql上遇到各類問題,爲了解決這些問題引入了同義詞和連接服務器的概念(19題考察的就是這個),這下覺得沒啥事情了,發現...什麼狀況,增刪改各類慢?查詢卻是還行。
細細研究發現,我去,是索引的問題(16,20題考察的內容)。而後借鑑MySQL的相關概念,他們每天說什麼讀寫分離,那麼咱們是否是也能夠走一個呢?因而就搞了多個庫,2個讀1個寫。這時候想到一個問題!數據同步怎麼辦?數據怎麼保證一致性?!!!
因而就有了發佈訂閱(這個裏面又有兩種,一種是主數據庫一改變就推送給從數據庫,一種是從數據庫按期向主數據庫發起同步請求【效率低】)這種讀寫分離,主數據庫進行增刪改,2個從數據庫只用來查,只給新手讀庫的權限,不再用擔憂他們修改不加where了~
後來就是業務問題了,我點,我點,我再點~我去,報了一個莫名的錯誤怎麼辦?
靠,是誰刪了這條數據!怎麼知道?
靠,磁盤快滿了,怎麼沒人說?!!
不用擔憂==》引入數據庫異常預警的功能(XEVENT+數據庫發郵件)【這個是站在前人肩上的成果】
如今:集羣怎麼搞?故障轉移怎麼走起?逆天正在研究中........
若是通過上面優化並且數據庫數據不算大(百G左右吧),那麼能夠得出個結論==》代碼太爛,重構去,二期走起~
22. 設計題:請根據如下圖設計一下商品相關的簡表(不包含活動、訂單、運費等)
a. 畫出設計圖【主要考察是否有必定的真實項目經歷】
b. 寫出建庫建表語句(每一個表數據很多於3個)【主要考察SQL基礎】
建庫大家就本身慢慢建吧,我簡單設計了一個模型:(有不合理的設計歡迎提出)