SQL练习题之子查询

题目是 create table salesproduct (sid int,pid int)

要求:查出pid中包含1,2,(3或4)的sid

方法一使用独立子查询:

View Code
select 
sid
from salesproduct
where
pid
=1
and
sid
in(
select sid from salesproduct where pid=2 )
and
(
sid
in
(
select sid from salesproduct where pid=3)
or sid in
(
select sid from salesproduct where pid=4)
)

方法二:使用关联子查询

select 
sid
from salesproduct a
where pid=1
and exists
(
select 1 from salesproduct b where b.pid=2
and b.sid=a.sid)
and exists
(
select 1 from salesproduct c where c.pid in (3,4)
and c.sid=a.sid)

方法三:使用表自连接

select 
distinct a.sid
from
SalesProduct a
join salesproduct b
on a.sid=b.sid
join salesproduct c
on b.sid=c.sid
where
a.pid
=1 and b.pid=2 and c.pid in(3,4)

方法四:类似数据透视

 
select
sid
from
(
select sid,
max(case when pid='1' then '1' end) as p1,
max(case when pid='2' then '2' end) as p2,
max(case when pid='3' then '3' end) as p3,
max(case when pid='4' then '4' end) as p4
from
dbo.SalesProduct
group by sid
)
as t
where t.p1='1' and t.p2='2' and (p3='3' or p4='4')

 想一想,如果得到

1 1,2,3,4

2 1,2

3 1,2,3

4 1,2,4

这样的结果呢?字符串的连接,可以使用coalesce结合透视完成.

select *
from
(
select sid,
coalesce(max(case when pid='1' then '1' end),'')+
coalesce(','+max(case when pid='2' then '2' end),'') +
coalesce(','+max(case when pid='3' then '3' end),'')+
coalesce(','+max(case when pid='4' then '4' end),'') as pidlist
from
dbo.SalesProduct
group by sid
)
as t
where pidlist in ('1,2,3,4','1,2,3','1,2,4')

select
sid,
convert(varchar,coalesce([1],''))+
convert(varchar,coalesce([2],''))+
convert(varchar,coalesce([3],''))+
convert(varchar,coalesce([4],'')) as pidlist
from SalesProduct
pivot
(
max(pid) for pid in ([1],[2],[3],[4])
)
as x

第八章文中提到了字符串串联聚合的专用解决方案,使用for xml path('')技术,代码如下:

select
sid,
stuff((select ','+ convert(varchar,pid)
from dbo.SalesProduct as b
where b.sid=a.sid
order by pid
for xml path('')),1,1,'') as [pidlist]
from SalesProduct as a
group by sid

 使用子查询的时候要注意一个陷阱,就是名称解析是从内部嵌套到外层的,如果你在嵌套层中select的列名不存在于嵌套查询的表中,而存在外表的时候,也不会报错,只是可能不是你要的结果.所以要注意.最好使用表别名.(inside sql server 2008)

题目2 :生成数字辅助表

一般直接用循环了,可是会产生很多的日志记录,所以速度会很慢.inside sql server 2008上介绍的方法,使用折半批量插入,利用到了sql本身集合操作的特点,还有一种常用的方法就是使用小的辅助表如果(0-9)的小表使用笛卡尔积的方法来插入.效果会更好.

  

 

posted on 2011-08-05 13:29  tneduts  阅读(583)  评论(1编辑  收藏  举报

导航