SQL Server数据库培训——子查询

上一篇 / 下一篇  2011-03-31 14:35:59 / 个人分类:数据库

1.            子查询(subquery

SQL支持在查询语句中编写查询或者嵌套其它查询。外层查询返回结果给调用者,内层查询(也称子查询)返回数据供外部查询使用。

3Ui9N/UzMD0

通俗点说子查询是嵌套在SELECTINSERTUPDATEDELETE语句的WHERE子句和HAVING子句中的另一个SELECT语句。51Testing软件测试网 fyv)_@C;a R1E B

1.1         子查询类型

子查询可以分成独立子查询(self-contained subquery)和相关子查询(correlated subquery)51Testing软件测试网&^t$@j'P#vRq_;j-D&W

独立子查询的特点是不依赖于外部查询,可以独立运行。而相关子查询需要依赖于它的外部查询。51Testing软件测试网\k y$VS]

独立子查询又分为标量子查询(scalar subquery)和多值子查询(multi-valued wubquery)和表子查询(table wubquery)。51Testing软件测试网#t[5D;sK/O4m"X|Bh$YT

子查询又分单列子查询和多列子查询,这在后面会讲到。51Testing软件测试网4B#v~V/A @

1.1.1            独立子查询

独立子查询是独立与外部查询的子查询,它总是可以拿出来单独运行。这种语句的执行分两个步骤:首先执行内部子查询,然后根据子查询的结果再执行外层查询。外部查询返回所有结果有调用者。子查询只运行一次

4oQJ+w5}0

1.1.1.1   标量子查询

标量子查询,由比较运算符(=、><<=>=)引出的子查询。在使用单一比较操作符引出子查询时,必须保证子查询返回一个单值,否则将引起查询错误51Testing软件测试网%g#S'Z%L$JyAf

1.1.1.1.1         单行单列子查询

例子一:where条件中使用子查询51Testing软件测试网w.|&`K$d+f6qu

SELECT *

O%] v9ow,Qa{0

FROM USER

NpXK0\&\2S'i.O0

WHERE user_id = (SELECT51Testing软件测试网7z:RN+},m$F m

                  ownerid51Testing软件测试网$C oD/W,t!i

                FROM dealers51Testing软件测试网$m@,tUe%O

                WHERE ownerid > 0)

;~+gZ2AG3P6r?W0

例子二:在delete条件中使用子查询

XtG$}1n0

DELETE

DS? SS0

FROM USER51Testing软件测试网xn;M&n7h'e

WHERE user_id>=(SELECT51Testing软件测试网|7PC [^F

                  Avg(ownerid)51Testing软件测试网0\Qn5_CO%C

                FROM dealers

|c:m8}#U`2l0

                WHERE ownerid > 0)51Testing软件测试网6k(TO3w+anq~m[

 51Testing软件测试网#Ir]vJ!~)e8n2]

      例三:在select中使用子查询

j9GH#AZ5Y:as%e0

SELECT

b RM:`Z Xp5T0

 d.DealerID,51Testing软件测试网WM ^._ ~E

 d.DealerName,51Testing软件测试网2n0{MBT2J C;l9x(I

 (SELECT51Testing软件测试网/^&\juL%t

    u.login_name

i)l&^ST0

  FROM USER u51Testing软件测试网m4qPC g~}

  WHERE u.user_id = d.OwnerID)   username51Testing软件测试网%ogMW`K)t

FROM dealers d

%a-`k#I+y"oT j#]W Wl0

例四:在from子句中51Testing软件测试网 B%{A O4JN+j*stZ

SELECT

Q+[*_y$oY1Cn aP4h0

 u.user_id,

\ `3Et @3UF0

 d.DealerID,

L)U F9MMy0

 d.ownerid

;P#~A4QsM$Y3q G1AOY0

FROM USER u,

G,A A[[Vv"P0

 (SELECT51Testing软件测试网Q%ad`4{?

    d.DealerID,51Testing软件测试网@5X a } hBa*z

    d.ownerid

S0]#V9R'E4{1V0

  FROM dealers d51Testing软件测试网[9C t$}2Z8[%^

  WHERE d.DealerID = 1425) d51Testing软件测试网$r*?;ReLSh

WHERE u.user_id = d.ownerid

$J;hV!G dg,I5i0

上面所有例子中我们可能看到子查询51Testing软件测试网#A+Mn4jA?,r B S

SELECT51Testing软件测试网,M(S8R _ @!u8fO[6U?

 ownerid51Testing软件测试网4lw{-Ar

FROM dealers51Testing软件测试网M6d'K5V,i:}r X&CS

WHERE ownerid > 051Testing软件测试网+n.k'NwE4l7TS

是可以单独拿出来执行的。不会有语法错误。51Testing软件测试网!|!\ @9k{&A*Z1xU.B

1.1.1.1.2         单行多列子查询

当是单行多列的子查询时,外部查询语句的条件语句中引用子查询结果时也可用单行比较符号来进行比较(成对比较)。例如:

!i?PP-R$q0

SELECT *51Testing软件测试网"G8b\.O+u7]4|)L

FROM USER u51Testing软件测试网f|zNCc&tq @#{

WHERE (user_id,login_name) = (SELECT51Testing软件测试网&WEd1cg\?

                               u2.user_id,

)f3J'Odc7Q9B%}|.V+p0

                               u2.login_name51Testing软件测试网F Id u@wcS

                             FROM USER u2

+^0[;g|`6Q ]8s0

                             WHERE u2.user_id = 1)

4^9x%JoV#f0

      单行多列子查询不能用在select子句中。51Testing软件测试网F5R:pvf+fAv

1.1.1.2   多值子查询

子查询返回多行数据叫多值子查询.关键字IN可以处理多值子查询。51Testing软件测试网"o}KU.U4m

例一:

rOL.E;m|1e0

SELECT *

(wR&}%RXw~0

FROM USER51Testing软件测试网.l,jugAx@a7]

WHERE user_idin(SELECT51Testing软件测试网-z%?Q5N(I%X0})l3L

                  ownerid51Testing软件测试网h,W%py9F])g|'L.]R

                FROM dealers

d(?I5UxY T \d[0

                WHERE ownerid > 0)

$q @*Y~GW0N&`0

      例二:

Q tBH-@+m/JB,O0

SELECT *51Testing软件测试网H~#c/c o"O

FROM USER51Testing软件测试网+U)n H)RJ)ANN

WHERE user_idNOT IN(SELECT

`%zNhxC$C0

                  ownerid

2t['U2I T~e0

                FROM dealers

(`A2l3?6ZY0

                WHERE ownerid > 0)51Testing软件测试网~"ir;Y-X'sz

 51Testing软件测试网yz"]IKX

      多值子查询也分为单列和多列两种类别,下面是一个多列的例子51Testing软件测试网-UaS$wv2A

SELECT *

T(]'q1n%~~Et'G]0

FROM USER u

*b+G,dx @S+~3H)N$t0

WHERE (user_id,login_name)IN(SELECT51Testing软件测试网 V+X vwUU%?$g2yD

                              u2.user_id,51Testing软件测试网^8X.T)Oj#]4fM+s%z

                              u2.login_name

N!d}L f6~ w;i0

                            FROM USER u2

?h5d,[EH&xB0

                            WHERE u2.auth_email = 1)

*t O|f z4ssn(q0

1.1.2            相关子查询

相关子查询是指引用了外部查询中出现的表的列的子查询。这就意味着它不能被单独地执行。

/fkK"I k-N5o,M4dQ0

以下是相关子查询的举例51Testing软件测试网)z,\2^WQS"hb

例一:

q JO8Z J'Tk4t/S0

SELECT *51Testing软件测试网 q F` U8j6qT2J

FROM relation_customer_product rcp51Testing软件测试网p)\q:_ z*h%ko.x

WHERE rcp.billing_id = (SELECT51Testing软件测试网"Ptv IF3s

                         MAX(rcp1.billing_id)51Testing软件测试网 K ^$@0`$k]"K!V

                       FROM relation_customer_product rcp1

} Mm;O]8_,|0

                       WHERE rcp1.operator_id = rcp.operator_id)

U8\+k6A u?/Q0

上面的SQL返回的结果是所有注册人员注册的最后一个BBN用户信息。51Testing软件测试网v MQM/Z_ h#j |1L

在逻辑上相关子查询会为每个外部行单独计算一次,也就是说上表relation_customer_product中有多少行数据子查询就执行多少次。51Testing软件测试网)H G ?B&?q)f

当外部查询运行到第一行时,比如上表中RCP.operator_id= 571508时,子查询筛选出当前operator_id最大billing_id返回给外部查询,外部查询判断当前的billing_id是否等于子查询返回的billing_id,是则返回给用户,不是则不返回该行。依次类推。

3t] zL7ri'w"{0

相关删除举例

J ~ \ RG0

Delete51Testing软件测试网d&w!e(y.O)E F

FROM relation_customer_product rcp51Testing软件测试网aTV2G |4Ni]Fg{Q

WHERE rcp.billing_id = (SELECT

{F6\-gHk%q6?X2N0

                         MAX(rcp1.billing_id)

"DJL~&ax/L JuAt0

                       FROM relation_customer_product rcp151Testing软件测试网)pV$\ow C M

                       WHERE rcp1.operator_id = rcp.operator_id)

~h6_`9{*X:{0

 

:@(g+y9J3O0

同样的相子查询也分为单行单列、单行多列、多行单列、多行多列四种情况。不再详细描述。

#c%Ti_| Mk+x0

1.1.2.1   EXISTs子查询

子查询支持exists谓词,它的输入是一个子查询。如果子查询能返回任何行,则exists返回true,否则返回false.51Testing软件测试网z eAW"I3i2{J

SELECT *

"[ @H.^)r2mr*f0

FROM dealers d

|i+}&gM0

WHERE EXISTS(SELECT *51Testing软件测试网/PbSr9gSGm

            FROM USER u51Testing软件测试网 F r ZS7fu

            WHERE d.OwnerID = u.user_id)

.` w+QG Ea | z0

            

0tk a&X5t*C7iU0

EXISTS存在一个所谓的短路功能‘,也就是这个谓词只关系是否存在记录.IN的话每一次扫猫user表都需要扫描完表的数据.EXISTS当遇到存在的user_id会返回trueflase然后就不继续扫表下面的数据了

p nX_8~ars0

      所以下面的这个SQL51Testing软件测试网I|Y6~od$OO(n

SELECT *51Testing软件测试网!~{$t.]"S4n UW4i:i3f

FROM dealers d

X"X1n[}0

WHERE ownerid IN (SELECT user_id

&TxbG6ox0

            FROM USER u51Testing软件测试网Cmz;?'e5u\!C

            WHERE d.OwnerID = u.user_id)

dQ%r6E;Z$V+_V!G-o0

      可以替换成51Testing软件测试网p bs_ P,bi

SELECT *51Testing软件测试网-w }&Z v"@c y

FROM dealers d51Testing软件测试网Dv} N|

WHERE EXISTS(SELECT *51Testing软件测试网^y3i:E{[j1X{

            FROM USER u

^"@a6z;LW1D$ecE0

            WHERE d.OwnerID = u.user_id)

d*J(h;ZiM'a3`0

TAG:

 

评分:0

我来说两句

Open Toolbar