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

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

1.            子查询(subquery

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

"J p \`1b I0

通俗点说子查询是嵌套在SELECTINSERTUPDATEDELETE语句的WHERE子句和HAVING子句中的另一个SELECT语句。51Testing软件测试网 VK6R.y:a4L[

1.1         子查询类型

子查询可以分成独立子查询(self-contained subquery)和相关子查询(correlated subquery)51Testing软件测试网r}DaUN

独立子查询的特点是不依赖于外部查询,可以独立运行。而相关子查询需要依赖于它的外部查询。51Testing软件测试网z8_+C:Zc*Bk

独立子查询又分为标量子查询(scalar subquery)和多值子查询(multi-valued wubquery)和表子查询(table wubquery)。

.vvDtsm}[0

子查询又分单列子查询和多列子查询,这在后面会讲到。51Testing软件测试网 Z PY4xJG/u

1.1.1            独立子查询

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

1.1.1.1   标量子查询

标量子查询,由比较运算符(=、><<=>=)引出的子查询。在使用单一比较操作符引出子查询时,必须保证子查询返回一个单值,否则将引起查询错误

z$fm-V;H7Ap'u0
1.1.1.1.1         单行单列子查询

例子一:where条件中使用子查询

s u]5ZV+S-c#N0

SELECT *

1CW K)x%|0w+[0a8O4Nm0

FROM USER51Testing软件测试网2~w4_Mw

WHERE user_id = (SELECT

5`c1LvfMK&h;z0

                  ownerid

A7s@T jqi\0

                FROM dealers

P'DE$?4Wg@|vA0

                WHERE ownerid > 0)

p7_[0P'e!V I*xk0

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

9Atai4` Lm~0

DELETE51Testing软件测试网w.cZ!kE'Ba#r

FROM USER51Testing软件测试网 Th8^#fJ1K$M%Y:U3a

WHERE user_id>=(SELECT

&BP bY7d V#[ g0

                  Avg(ownerid)

_xlEQ){Tv0

                FROM dealers51Testing软件测试网NAea]m9jY?0S

                WHERE ownerid > 0)51Testing软件测试网K8V*uC%P}dpM

 

I*m)P U0jI0

      例三:在select中使用子查询

GM vcCN U0

SELECT

+rvL%NF eKG0

 d.DealerID,

y&O)@~O.`)U0

 d.DealerName,

H yG,C4PJ0

 (SELECT51Testing软件测试网7G;w%Y Oc ?0io9y

    u.login_name51Testing软件测试网4a/^Ik%` ~M?

  FROM USER u

1|[4@J(J `4W0

  WHERE u.user_id = d.OwnerID)   username

n9dOPK[2tm S-L0

FROM dealers d

-O-S.L7?/EUV B4C0

例四:在from子句中

DLG{ ne{Xu,u0

SELECT51Testing软件测试网'i)K'o8k\-y-i PJw

 u.user_id,51Testing软件测试网}`3R\;U

 d.DealerID,51Testing软件测试网Z7bA q }5iZ

 d.ownerid

!Q,@Gib0

FROM USER u,

e Y|R,I6s;Z_#H8Ka&\0

 (SELECT

pu(t[z4e9] Q"m0

    d.DealerID,

(t5@(?0D{4W$Wf YE0

    d.ownerid51Testing软件测试网/qKI6_#D&E&e

  FROM dealers d

]})sOOVJ'v ~gqQ0

  WHERE d.DealerID = 1425) d

#Z-eI#b:BgL!o0

WHERE u.user_id = d.ownerid51Testing软件测试网9lJR\CGh;x

上面所有例子中我们可能看到子查询

,u;N@0u1J-V0

SELECT

4YgK$c,} u0

 ownerid51Testing软件测试网(x6gt'xR'P [ w

FROM dealers51Testing软件测试网@{p!zg$]2~%D

WHERE ownerid > 0

7Q0H F&s,^0

是可以单独拿出来执行的。不会有语法错误。

@-IcwY0
1.1.1.1.2         单行多列子查询

当是单行多列的子查询时,外部查询语句的条件语句中引用子查询结果时也可用单行比较符号来进行比较(成对比较)。例如:51Testing软件测试网 e[5W4e*v

SELECT *

It1M7SZ2m0

FROM USER u

X ?F N6o0

WHERE (user_id,login_name) = (SELECT51Testing软件测试网&B5p9|_)p1C

                               u2.user_id,51Testing软件测试网Ik ]4BS2fT,y

                               u2.login_name51Testing软件测试网J#pF A+~:XB]

                             FROM USER u2

;b;qyAa1b0

                             WHERE u2.user_id = 1)51Testing软件测试网V:`W$} _

      单行多列子查询不能用在select子句中。51Testing软件测试网mzs$_~

1.1.1.2   多值子查询

子查询返回多行数据叫多值子查询.关键字IN可以处理多值子查询。51Testing软件测试网\aI(w)P0B.S hC

例一:

q(i p4y+Jb/e6w0

SELECT *51Testing软件测试网 e&} [Ts(\!{

FROM USER51Testing软件测试网d)h;T9PwDO

WHERE user_idin(SELECT51Testing软件测试网hEB'W!Jc

                  ownerid51Testing软件测试网HAI!?1{j@_O

                FROM dealers51Testing软件测试网(X,t g4v"o+WzY

                WHERE ownerid > 0)51Testing软件测试网5PKkn liM@C

      例二:51Testing软件测试网5o%r7Z`(trx }8@

SELECT *51Testing软件测试网k\:NkO%s#zpbn*A

FROM USER51Testing软件测试网t@m uO5f$k

WHERE user_idNOT IN(SELECT

,pR r"i8IW:d H4E0

                  ownerid

g#w!{'i#W\/_y~0

                FROM dealers51Testing软件测试网%@\qe(`t

                WHERE ownerid > 0)51Testing软件测试网bj ^d(T9E9s

 

+F[W ~&?Mh H2Z0

      多值子查询也分为单列和多列两种类别,下面是一个多列的例子

yF;i"[+?+\o5z6F0

SELECT *51Testing软件测试网f hf+KLu;M

FROM USER u

.BOB g#s2Az0

WHERE (user_id,login_name)IN(SELECT

/[_'Y}9O0M0

                              u2.user_id,

P&o6| QuP0

                              u2.login_name51Testing软件测试网)m&Z pttx}|

                            FROM USER u251Testing软件测试网td#H$SKj!D? Y

                            WHERE u2.auth_email = 1)51Testing软件测试网~O9eT O#x[

1.1.2            相关子查询

相关子查询是指引用了外部查询中出现的表的列的子查询。这就意味着它不能被单独地执行。51Testing软件测试网*U m#k:_,u IV7|Ms

以下是相关子查询的举例51Testing软件测试网3uo{4kE'?lh

例一:51Testing软件测试网4^7^Ee-j q J!Y

SELECT *51Testing软件测试网 Y#\-rD&u*O

FROM relation_customer_product rcp51Testing软件测试网4BS*k-x1tm

WHERE rcp.billing_id = (SELECT

sxn PxQ x0

                         MAX(rcp1.billing_id)

4^x BNb0

                       FROM relation_customer_product rcp151Testing软件测试网 ~ [k]zM

                       WHERE rcp1.operator_id = rcp.operator_id)

r#H1ml1v Y,[0

上面的SQL返回的结果是所有注册人员注册的最后一个BBN用户信息。51Testing软件测试网 ~ L-ksC(I+@

在逻辑上相关子查询会为每个外部行单独计算一次,也就是说上表relation_customer_product中有多少行数据子查询就执行多少次。51Testing软件测试网8Z%\%nplh}m(n3c

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

~6rvK3H,NN,t'R0

相关删除举例

7J4{AX*r\0

Delete51Testing软件测试网!t[n FoK

FROM relation_customer_product rcp51Testing软件测试网9F3yYli8?-q&X

WHERE rcp.billing_id = (SELECT

|!a)Cr:}7y{0

                         MAX(rcp1.billing_id)

6TCr5Oh;}D6Gh0

                       FROM relation_customer_product rcp151Testing软件测试网)F3`3M ^&q:v5o Qm

                       WHERE rcp1.operator_id = rcp.operator_id)51Testing软件测试网rB \R#A+{E

 51Testing软件测试网vI)EXjBF6b

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

n"gL3pL0

1.1.2.1   EXISTs子查询

子查询支持exists谓词,它的输入是一个子查询。如果子查询能返回任何行,则exists返回true,否则返回false.51Testing软件测试网*{.i3}se o]{!l?!]

SELECT *

aN7M8@5C6u0

FROM dealers d

c?"\O*a:e`Yt0

WHERE EXISTS(SELECT *51Testing软件测试网)_J.YsaHf4lb{

            FROM USER u51Testing软件测试网}o7V#|E0J^)jV

            WHERE d.OwnerID = u.user_id)51Testing软件测试网(\U;ia fW@N

            

!G2o:[ V/Pe0

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

{h![4L7~0m-v0

      所以下面的这个SQL51Testing软件测试网aV,b\8C

SELECT *51Testing软件测试网9y pO4m L5Yua

FROM dealers d51Testing软件测试网-J8h,V#~)wt[

WHERE ownerid IN (SELECT user_id51Testing软件测试网/odA[ PoH"A"t{$m

            FROM USER u

N#u_ ?,F4ROP0

            WHERE d.OwnerID = u.user_id)51Testing软件测试网\XiYufa

      可以替换成51Testing软件测试网 DYZx/fvB

SELECT *

|S9O N;l {]i:V0

FROM dealers d51Testing软件测试网]p@5s_,|ia

WHERE EXISTS(SELECT *51Testing软件测试网j:Kc)J;d._

            FROM USER u

I5sy)dKu0

            WHERE d.OwnerID = u.user_id)51Testing软件测试网&g6aL_rQ}LgD4SV


TAG:

 

评分:0

我来说两句

Open Toolbar