server多笔记录拼接字符串 sql_第四章、SQL Server数据库查询大全(单表查询、多表连接查询、嵌套查询、关联子查询、拼sql字符串的查询、交叉查询)...
4.1、查詢的類型
declare @value as int
set @value = 50
select? 'age:'as age,2008 years,@valueas va
--這種查詢時跟表沒有關系的
select ?'age:'as age,2008 years,@valueas vafrom student
--這種查詢涉及到表,表有多少行就查詢出多少行,但是沒有涉及到表的列
select 'age:' age,Sage,2008 years,@valueas va from Student
--這種是外面的列與表中的列的綜合
4.2、單表查詢
4.2.1、列名的別名和表名的別名
select Sno, Sname,2008-Sagefrom student
--2008-Sage可運算,但無列名
select Sno xuehao, Snameas xingming,2008-Sage shengrifrom student
--給列名取別名既可以加as也可以不加
select Sno,Sname,2008-Sageas shengrifrom studentorderby shengri--where shengri > 1983
--shengri字段即屬性的別名是不能用來作為判斷條件使用的,但是可以排序
--原列名既可以作為判斷條件,也可以排序;列名的別名只能用作排序,不能用作判斷條件
select Sno,lower(Sdept) sdfrom student--lower(Sdept),但無列名
select 'age:' age,Sage,2008 yearsfrom Student
select ss.Sno, Sname,2008-Sagefrom student as sswhere ss.Sno='95001'
select ss.Sno, Sname,2008-Sage agefrom student ss where ss.Sno='95001'
select ss.Sno, Sname,2008-Sagefrom student as ssorder by ss.Sno
--select ss.Sno as n, Sname ,2008-Sage from student as ss where ss.n='95001'這個SQL語句是錯誤的.
--select ss.Sno as n, Sname ,2008-Sage from student as ss order by ss.n
--這種排序是錯誤的.
--表名也可以有別名,給表名取別名既可以加as也可以不加;用表名或者表明的別名來引用列名,既可以排序也可以作為判斷條件;用表名或者表明的別名來引用列名的別名,既不可以排序也不可以作為判斷條件
4.2.2、消除重復行distinct
select distinct Snofrom SC
--消除取值重復的行,關鍵字是distinct,默認缺損值是ALL,這個是針對某一行而不是某一個字段,也就是說各行之間的各個字段完全相同才算是重復的,而不是只有某一個字段相同就算重復了
4.2.3、比較運算符、not運算符
select Sname from Student where sdept = 'CS'
select Sname ,Sage from Student where Sage<=20
select distinct Snofrom SCwhere not grade < 60
--比較運算符:> >= < <= = != <> !> !<
--not運算符:是針對某一個邏輯表達式(bool表達式)的,是對邏輯表達式取反的,而不是針對一個符號,比如grade not< 60,所以運算符NOT可以與比較運算符同用,對條件求非,比如not grade < 60
4.2.4、確定取值范圍between...and...
select Sname,Sagefrom studentwhere sagenot between 22 and 20
--確定取值范圍:between...and...,not between...and...
--注意:betweenA? and? B?這個相當于>=A? and<= B,?順序不能錯!不會對A,B的大小進行檢查
4.2.5、確定集合:in、not in
select Sname,Sage,sdeptfrom studentwhere sdeptin ('CS','ma')
--確定集合:in,not in , in可以用= OR =等等來替代,not in可以用!= and!=
--注意:加了括號的
4.2.6、模糊查詢like
select *from studentwhere sno= '95001'
select *from studentwhere snolike '95001'
select *from studentwhere snamelike '劉%'
select *from studentwhere snamelike '劉_'
select *from studentwhere snolike '9500_'
select *from studentwhere snamelike '_呈%'
select *from studentwhere snamenot like '劉%'
SELECT *FROM COURSE
select *from coursewhere cnamelike 'DB\_M' escape '\'
select *from coursewhere cnamelike 'MA\%S' escape '\'
select *from coursewhere cnamelike 'MA%K__'
--字符匹配[not]like % _ escape
--當like后面的字符串沒有包含通配符的時候,like就是=
--%:通配符,代表任意長度的字符串包括0.
--_: 代表一個字符.默認每一個字符(數值,字母,漢字)采用ascii進行編碼的.但是
管用什么方式進行編碼,_代表的是一個字符,而不是一個字節.
--escape定義某一個字符,這個字符后面緊跟的通配符是不起通配作用的,當like比較的時候會忽略字符串中的escape定義某一個字符,而把其后的通配符當成一個普通的字符。
4.2.9、涉及空值null的查詢
select *from studentwhere sname= ''
select *from studentwhere ssexis null
select *from studentwhere snameis not null
--涉及空值的查詢:is not null
--當是空值的時候只能用IS來判斷,其他的都不可以.
--null表示什么都沒有,而''表示的是長度為零的字符串
--null與任何類型的值進行算術運算的結果都為null
4.2.10、多重條件查詢and、or
select * from student where sdept = 'cs' and sage< 22
--多重條件查詢andor
--and表示的是并且,而or表示的是或者
--and的優先級比or高,但是()可以改變優先級別
4.2.11、對查詢結果進行排序
select *from SCwhere cno= '3' order by gradedesc
select * from SC order by sno,grade
--排序order by asc/desc
--asc是升序,是默認的缺損值,desc是降序的
--order by a,b,c,d像這種按照多個字段進行的排序,先按照第一個字段排序,再按照第二個字段排序,以此類推,但是第二個字段的排序是在第一個的基礎上進行的,它不會去打亂第一個排序的,第一個排序其實就已經分成組了,第二個排序是在第一個排序的各個小組里面進行的排序.
4.2.12、集函數(count、avg、sum、max、min)
select *from student
select count(*)from student
select count(all sno) numfrom student
select count(distinctsno) numfrom student
--select count(distinct *)from student--為什么*的時候不能加distinct?
--select count(all *)from student--為什么*的時候不能加all?
select avg(distinct sage)from student--必須是數字,非null值的加和除以非null值的個數
select sum(distinct sage)from student--必須是數字,非null值的加和
select max(distinct sno)from student--只要是可以比較大小的就可以,如果該列全是null,那么結果也是null
select min(distinct sno)from student--只要是可以比較大小的就可以,如果該列全是null,那么結果也是null
--對于這些集函數,dinstinct表示消除了重復的行,而默認缺損為all
4.2.13、分組查詢group by
select *from sc
select cno from sc group by cno
—-分組之后,一組中只取一個值,而不會取出多個重復的值,哪怕沒有distinct也是這樣的,所以如果要加其他的列,這些列在一組中要保證只有一個值。所以每一組只會有一行。
select cno,snofrom scgroup by cno,sno--分組是不會排序的
select cno,snofrom scgroup by cno,snoorderby cno
select cno,count(sno)from scgroup by cno
select sno,count(cno) cnoNumfrom scgroup by sno
having count(distinct cno)>=3
select cno,count(sno)from scwhere cno>1groupby cno,sno
having count(sno)>0orderby cno
--注意上面這個sql語句的順序,執行的順序是先分組,然后查詢計算,然后在查詢
--的結果中判斷where和having條件,最后去排序.
--分組與不分組的區別是:不分組的時候,(如果是多表的話,先要去連接)先查詢,
--然后在查詢結果中按照where子句的條件來篩選。而分組的時候,
--(如果是多表的話,先要去連接)是先分組,然后再執行查詢,然后在查詢結果中
--按照where子句和having子句的條件來篩選。Having后面的集函數是對每一最小組(按照group by后面的所有列進行的分組,是所有列而非某一列分組)的那些行進行運算的。另外,having后面也可以對某列進行非集函數的條件判斷,這種判斷也是針對每一最小組的那些行。
select top 10 a.sno,count(distinct cno) cno_num
from student as a,sc as b
where a.sno= b.snoand a.sno ='95001'
group by a.sno
having count(distinct cno)>= 2
order by a.sno
查詢的執行步驟:先連接,然后按照條件去分組,然后按照組查詢,先查詢第一組(第一行),然后用where子句和having子句的條件來篩選,滿足條件就保留,否則就舍去,然后查詢第二行......,最后在查詢出的結果中排序,然后在排好序的結果中去求top n。
小結:
1、分組是按照某個列來進行分組的,最后在該列中列值相同的就是一組了,group by a,b,c先按照a進行分組,在按照a分好的每一組里面,再按照b進行分組,即保留了最開始的組,然后在按照b分好的組里面再按照c進行分組,以此類推......
2、分組是不會排序的,排序和分組是兩個獨立的過程,排序是在分組查詢之后,在最終的滿足各種條件的查詢結果里面來排序.
3、如果在分組的時候要查詢某些字段,那么一定要保證在最小組中的該字段是絕對唯一的,因為每一個最小組最后只會有一行記錄,有時候,用戶知道是絕對的唯一的,但是計算機不知道,所以在這種情況下必要的時候可以再按照該字段進行一次分組,或者使用集函數.在使用集函數進行運算的時候,是對對最小的組進行計算.
4、沒有分組的時候判斷條件用where,分組之后對于某一組的集函數結果的判斷條件是having,一般用于集函數count,分組后對于某一個字段的判斷還是用where
2008-07-13
4.3、多表連接查詢
4.3.1、連接查詢概述
在關系數據庫的查詢中,單表查詢是有很大的局限性的,因為多數情況下各個表之間都是有關聯的,所以絕大多數情況下都要多表連接查詢:
1、無條件連接
無條件連接其實就是廣義笛卡爾乘積,即一個表(m行)中的每一行都與另外表(n行)中的每一行聯合,最終構成了一個m*n行的一個表。
2、有條件連接
有條件連接顧名思義就是兩個表之間的連接是有條件的,其中一個表的某一個字段與另外一個表中的某一個字段以某一種條件聯系起來,連接的過程就是先掃面表1的第一行,去與表二中的每一行對比,滿足條件的就選擇出來,然后拿表一中的第二行去做相同的操作,一直到最后完成。很顯然,這個連接后的表其實是廣義笛卡爾乘積的子集。這種條件如果是不相等的話,那么就是非等值連接,反之就是等值連接。非等值連接用的比較少,主要是等值連接。
3、等值連接
當一個表的某一個字段與另外一個表中的某一個字段的聯系條件是相等的時候,那么這種連接就是等值連接。在等值連接中,如果消除了重復的列,那么這樣的等值連接就是自然連接。在自然連接中,滿足條件的才會被選出來成為新的行,不滿足條件的是不會被選擇出來的。其實自然連接就是內連接。
4、外連接
在兩個表之間,如果某一張表的行與另外一張表對應的時候,出現了根據條件去篩選另外一張表的全部行,而前一張表仍有未對應的行,那么這些行是不會成為新表中的行的,但是如果想把這些沒有對應的行顯示出來,就要用到外連接了。如果表一和表二連接,在表一中存在沒有連接的行,表二中全部用NULL來補充,缺損的就是NULL,所以此時稱為左外連接,反之則是右外連接。
左外連接:就是以左邊的行為主,左邊的全部都要顯示出來,右邊與之對應的要顯示出來,沒有與之對應的就補null。至于右邊是否對應完了,不用考慮。
右外連接:就是以右邊的行為主,右邊的行要全部顯示出來,左邊與之對應的顯示出來,沒有對應的補null。至于左邊是否對應完了,不用考慮。
4.3.2、連接查詢的列名
對于查詢時候的字段名字,某個字段如果在兩個表中都是唯一的,沒有重復的,那么就直接用字段名字,當然,如果用表名.列名更穩妥,但是建議只用字段名;對于那些在兩個表中有相同的字段的,那么一定要用表名.列名,此時的列名一般就是按照例名來編號,這樣顯然不好,一般要用別名比較好,那么這樣處理后在應用程序中引用的時候就非常方便,也不會出錯了。
注意:只要使用了別名,顯示出來的就是別名,而且應用程序中也是要通過這個別名來引用才不會出錯的。使用函數的時候一般也要用到別名。
4.3.3、兩張表以上的連接查詢
對于兩張表以上的內連接或者外連接,可以認為先讓前面兩張表連接起來,構成一個記錄集,然后讓把這個記錄集當成新的表與后面的表相連接。
4.3.4、連接查詢實例
4.3.4.1、內連接查詢實例
方法一:用=號內連接
use zwj_study
select *from student
select *from sc
select *from course
select student.*,sc.*,sc.Gradefrom student,scwhere student.sno= sc.sno
--表名.*表示的是選擇了這個表中的所有列,所有列名都用了表名.列名
select student.*,course.*from student,sc,course
where student.sno= sc.snoand sc.cno = course.cno
--不管最終查詢的列是否在某個表中,但是只要這個查詢的條件中涉及到了這張表,那么就一定要在from中添加進來這張表
方法二:用inner join內連接
select student.*,sc.*from studentinnerjoin sc on student.sno= sc.sno
select student.*,sc.*,course.*from
student inner join sc on student.sno= sc.sno
inner join courseon sc.cno= course.cno
--以上是內連接的第二種寫法.這個連接的過程是前面兩張表先連接好了,然后再來連接第三張表。連接的條件已經在from里面了.當然還可以用where來添加新的條件
--select student.* ,sc.* from student inner join sc
--wherestudent.sno = sc.sno
--
--select student.*,sc.*,course.* from student inner join sc inner join course
--wherestudent.sno = sc.sno and sc.cno = course.cno
--
--以上的這兩種寫法是完全錯誤的,不能個這樣寫.
4.3.4.2、外連接查詢實例
select student.*,sc.*
FROM?? Student left outer JOIN SCON Student.Sno= SC.Sno
Where ……
select student.*,sc.*
FROM?? Student right outer JOIN SCON Student.Sno= SC.Sno
select student.*,sc.*,course.*
FROM?? Student left outer JOIN SCON Student.Sno= SC.Sno
right outer join course on SC.cno = course.cno
--連接的條件已經在from里面了.當然還可以用where來添加新的條件.
--select student.* ,sc.*
--FROMStudent left outer JOIN SC where Student.Sno = SC.Sno
--
--select student.* ,sc.*,course.*
--FROMStudent left outer JOIN SC
--right outer join course
--whereStudent.Sno = SC.Sno and SC.cno = course.cno
--
--以上這兩種方式是錯誤的
4.3.4.3、內外混合連接查詢實例
select student.*,sc.*,course.*
FROM?? Student left outer JOIN SCON Student.Sno= SC.Sno
inner join course on SC.cno= course.cno
2008-07-14
4.4、嵌套查詢
在關系數據庫的查詢中,單表查詢是有很大的局限性的,因為多數情況下各個表之間都是有關聯的,所以絕大多數情況下都要多表連接查詢,多表連接查詢只有一個select,但是有時候也用嵌套查詢來代替連接查詢,使得查詢之間的層次關系更加清晰。所謂嵌套查詢,就是在一個查詢語句中出現了多個select表達式。
4.4.1、子查詢作為主查詢的條件
4.4.1.1、帶IN謂詞的子查詢
select s1.*,s2.*from studentas s1,studentas s2
where? s1.sdept= s2.sdeptand s1.sname ='劉呈'--與劉呈同系(單表連接)
select s1.*from studentas s1,studentas s2
where? s1.sdept= s2.sdeptand s2.sname ='劉呈'--與劉呈同系(單表連接)
select *from student
where sdept in (select sdeptfrom studentwhere sname= '劉呈')--與劉呈同系
select *from student
where sdept in (select sdeptfrom studentwhere sname=
(select snamefrom studentwhere sno= '95002')
)
select student.sno,snamefrom student,sc,course
where student.sno= sc.snoand sc.cno = course.cno
and cname = '信息系統'--選修了信息系統
select sno,snamefrom student
where sno in
(select snofrom sc
where cno in
(select cnofrom course
where cname = '信息系統')
)--選修了信息系統
select sno,snamefrom student
where sno in
(select snofrom sc
where cno in
(select cnofrom course
where cname = '信息系統'
)
)and ssex = '女'--選修了信息系統,而且性別為女
小結:
1、嵌套查詢中的IN,表示某一個字段在某一個集合里面,集合中可能有多個也可能只有一個值,但是只會有一個字段
2、任何一個子查詢都是select塊,一定要加上(),否則就會報錯.
3、任何一個子查詢都不能用order by來排序,只能對最終的查詢結果進行排序
4、子查詢的結果只是作為父查詢的某一個條件而已,還可以用AND,OR等追加更多的條件
4.4.1.2、帶比較運算符(>,>=,)的子查詢
select *from student
where sdept = (select sdeptfrom studentwhere sname= '劉呈')
--當確定了一個子查詢的結果是單值的時候,父查詢的查詢條件就可以使用比較運算符,子查
詢必須在比較運算符的后面,而不能是前面
4.4.1.3、exists謂詞
if notexists(select sdeptfrom studentwhere sage>=30)
select *from student
if exists(select*from student where sage<30)
select *from student
--exists,not exists只能針對一個select語句,它返回的是一個邏輯值:true或者false,它主要應用于if語句的判斷的,特別是在插入某張表之前來判斷某條記錄是否存在的,它還可以作為where判斷條件
小結:以上的子查詢作為主查詢的判斷條件,有些時候,子查詢與主查詢時關聯的,有時候是不關聯的。
4.4.2、子查詢作為主查詢的列
4.4.2.1、case表達式作為主查詢的列
select sno,cno,grade,
(case
when sno = (select snofrom studentwhere sname= 'james')
then 'james'else'others' end)as name
from sc
--上面這個查詢是一個不相關子查詢,即子查詢與父查詢之間沒有關聯,執行的步驟是先查詢第一行的sno,cno,grade,case語句,然后查詢第二行的sno,cno,grade,case,第三行......
--case是一個表達式,它會返回單值
select sno,cno,grade,
(case
when sno = (select snofrom studentwhere sno= sc.sno)
then 'one'else'others' end)as name
from sc
--上面這個查詢是一個相關子查詢,即子查詢與父查詢之間有關聯,執行的步驟是先查詢第一行的sno,cno,grade,case語句,然后查詢第二行的sno,cno,grade,case,第三行......
--case是一個表達式,它會返回單值
4.4.2.2、查詢表達式作為主查詢的列
select sno,cno,grade,(select snamefrom student where sno= sc.sno )as name from sc
--當子查詢的結果只有一行一列的時候,還可以直接將子查詢作為主查詢的列,作為主查詢的列
--子查詢與父查詢相關聯
小結:以上兩種查詢的列都出現了特殊的列,而不是一個普通的列,這個特殊列就是一個表達式,這個表達式永遠都只會返回一行一列,即返回單值。每查詢一行都會執行一次特殊列表達式,得到一個列出來。子查詢與主查詢可能是關聯的,也可能是非關聯的。
4.4.3、子查詢作為主查詢的from對象
select a.sno,sname, gradefrom
student a ,(select sno,cno,gradefrom sc) b
where a.sno= b.sno
select count(*) from
(select clsbdh,count(*)as su?from z_hgzzzgroupby clsbdh having count(*)> 1) a
--在from中使用子查詢,子查詢的結果就是一個新的表,一定要給新表加一個別名,否則會出錯。這種在from中使用子查詢,是把子查詢作為from的對象了,這種子查詢與主查詢是永遠不會有關聯的,否則就不要把子查詢作為主查詢的from對象了。
4.5、關聯子查詢
子查詢的查詢條件不依賴于父查詢時,我們稱之為不相關子查詢,反之,則成為相關子查詢。相關子查詢只會發生在嵌套查詢中,但是在嵌套查詢中的一種情況下是不會發生相關子查詢的,這就是子查詢作為主查詢的from對象的時候。
下面以子查詢作為主查詢的where條件來講解關聯子查詢,關聯子查詢的執行過程如下,每一個子查詢被外部查詢的每一行執行一次:
例1:
執行過程:先查詢第一行,然后執行where的判斷,如果滿足條件,那么這一行就選擇出來,否則就舍去。在這一行中,子查詢中的outer.department_id就是父查詢中這一行的department_id的值,然后查詢第二行、第三行......
例2:
執行過程:先查詢第一行,然后執行where的判斷,如果滿足條件,那么這一行就選擇出來,否則就舍去。在這一行中,子查詢中的e.employee_id就是父查詢中這一行的employee_id的值,然后查詢第二行、第三行......
例3:
執行過程:先查詢第一行,然后執行where的判斷,如果子查詢查出來確實存在,那么exist就會返回true,那么這一行就選擇出來,否則就舍去。在這一行中,子查詢中的outer.employee_id就是父查詢中這一行的employee_id的值,然后查詢第二行、第三行......
例4:
執行過程:先查詢第一行,然后執行where的判斷,如果子查詢查出來確實不存在,那么not exist就會返回true,那么這一行就選擇出來,否則就舍去。在這一行中,子查詢中的d.employee_id就是父查詢中這一行的employee_id的值,然后查詢第二行、第三行......
2008-07-20
4.6、拼sql字符串的查詢
在存儲過程中,有些時候,要動態的查詢一些列,動態的變換條件,那么就要拼sql語句:
declare @sqlSelect as varchar(5000)
set @sqlSelect = 'select 1,1,1,null from #zwj1'
拼完之后,可以用exec命令去執行,但是執行結果是一個記錄集,哪怕只有一個值也是記錄集,執行的結果只能用一種方式取得,即定義一個與查詢結果相同的表,然后將結果插入到表中,該表可以是臨時表也可以不是,這個表一定要之前就定義好,列固定:
insert into zwjexec(@sqlSelect)
以下的用法都是錯誤的:
select *fromexec('select 1,1,1,null from #zwj1')
select *into #vfrom exec('select 1,1,1,null from #zwj1')
declare @k as int
set @k =exec('select count(*) from #zwj1')
update zwj set s = exec('select count(*) from #zwj1')
4.7、交叉查詢
在存儲過程中,有時候想把記錄集的行變成列查詢出來,那么就要用到交叉查詢,下面舉例說明交叉查詢:
例一:使用case表達式來實現交叉查詢:
每個行列轉換,都要經過三個邏輯處理階段,擴展階段是新增多個列,這樣將導致新增了一些行;分組階段將按照未轉換的列分組;聚合階段將對每個組進行處理,從而實現行的減少得到最終的結果。
以下是一張記錄表,phaseType這一列只有四個值,phase1、phase2、phase3、phase4,現在要把phaseValue這一列分成phase1、phase2、phase3、phase4四列的形式顯示出來:
那么就要交叉查詢:
select dmcode,klcode,phaseType,
case when phaseType='phase1'then phasevalueelse 0end phase1 ,
case when phaseType='phase2'then phasevalueelse 0end phase2 ,
case when phaseType='phase3'then phasevalueelse 0end phase3,
case when phaseType='phase4'then phasevalueelse 0end phase4
from PhaseInfo
查詢結果如下:
對以上查詢結果再進行一次轉換:
select dmcode,klcode,
sum(phase1) phase1,sum(phase2) phase2,
sum(phase3) phase3,sum(phase4) phase4
from
(
select dmcode,klcode,phaseType,
case when phaseType='phase1'then phasevalueelse 0end phase1 ,
case when phaseType='phase2'then phasevalueelse 0end phase2 ,
case when phaseType='phase3'then phasevalueelse 0end phase3,
case when phaseType='phase4'then phasevalueelse 0end phase4
from PhaseInfo
) A
group by dmcode,klcode
order by dmcode,klcode
查詢結果如下:
2010-01-22
總結
以上是生活随笔為你收集整理的server多笔记录拼接字符串 sql_第四章、SQL Server数据库查询大全(单表查询、多表连接查询、嵌套查询、关联子查询、拼sql字符串的查询、交叉查询)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【嵌入式学习-STM32F103-EXT
- 下一篇: oracle全局索引改成本地索引,解析一