首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > SQL Server >

考验你,这句SQL有点难!该怎么处理

2012-03-21 
考验你,这句SQL有点难!【情况描述】有表company,里面存放所有企业信息,其中有字段area_id表示该企业所属地区

考验你,这句SQL有点难!
【情况描述】
 有表company,里面存放所有企业信息,其中有字段area_id表示该企业所属地区的id,字段company_name表示企业名称。
 有表area,里面存放所有地区信息,其中有字段id主键(对应表company中的area_id),其中p_id是该地区的上级地区id(对应自身表的id),

p_id和id是自反关系,其中字段area_name表示该地区名称。
【所需结果】
 查询时通过传入的地区id来搜索company中的所有该地区的企业,以及该地区所有下级地区的所有企业(注意:该地区的下级可能还有下级)显示

结果包括company中的所有字段和area中的所有字段(如哪位能写出该SQL只需列出每个表中的一个字段即可如:company_name和area_name)

【要求】
 通过一条SQL或视图或存储过程实现

【最终结果】
 得到本人最真诚的感谢,和所有悬赏分。

[解决办法]

SQL code
--生成测试数据 create table tb(id varchar(3) , pid varchar(3) , name varchar(10))insert into tb values('001' , null  , '广东省')insert into tb values('002' , '001' , '广州市')insert into tb values('003' , '001' , '深圳市')insert into tb values('004' , '002' , '天河区')insert into tb values('005' , '003' , '罗湖区')insert into tb values('006' , '003' , '福田区')insert into tb values('007' , '003' , '宝安区')insert into tb values('008' , '007' , '西乡镇')insert into tb values('009' , '007' , '龙华镇')insert into tb values('010' , '007' , '松岗镇')go--创建用户定义函数 create function f_cid(@id varchar(10)) returns varchar(8000) as begin   declare @i int , @ret varchar(8000)   declare @t table(id varchar(10) , pid varchar(10) , level int)   set @i = 1   insert into @t select id , pid , @i from tb where id = @id   while @@rowcount <> 0   begin     set @i = @i + 1     insert into @t select a.id , a.pid , @i from tb a , @t b where a.pid = b.id and b.level = @i - 1  end   select @ret = isnull(@ret , '') + id + ',' from @t   return left(@ret , len(@ret) - 1)end go --执行查询 select id , children = isnull(dbo.f_cid(id) , '') from tb group by iddrop table tbdrop function f_cid/*id   children                               ---- ---------------------------------------001  001,002,003,004,005,006,007,008,009,010002  002,004003  003,005,006,007,008,009,010004  004005  005006  006007  007,008,009,010008  008009  009010  010*/(所影响的行数为 10 行)create table tb(id varchar(3) , pid varchar(3) , name nvarchar(10))insert into tb values('001' , null  , N'广东省')insert into tb values('002' , '001' , N'广州市')insert into tb values('003' , '001' , N'深圳市')insert into tb values('004' , '002' , N'天河区')insert into tb values('005' , '003' , N'罗湖区')insert into tb values('006' , '003' , N'福田区')insert into tb values('007' , '003' , N'宝安区')insert into tb values('008' , '007' , N'西乡镇')insert into tb values('009' , '007' , N'龙华镇')insert into tb values('010' , '007' , N'松岗镇')go;with t as(    select id , cid = id from tb     union all    select t.id , cid = tb.id     from t join tb on tb.pid = t.cid )select id , cid = STUFF((SELECT ',' + rtrim(cid) FROM t WHERE id = tb.id FOR XML PATH('')) , 1 , 1 , '')from tbgroup by idorder by id/*id   cid---- ---------------------------------------001  001,002,003,005,006,007,008,009,010,004002  002,004003  003,005,006,007,008,009,010004  004005  005006  006007  007,008,009,010008  008009  009010  010(10 行受影响)*/;with t as(    select id , name , cid = id , path = cast(name as nvarchar(100)) from tb     union all    select t.id , t.name , cid = tb.id , path = cast(tb.name as nvarchar(100))    from t join tb on tb.pid = t.cid )select id , name ,        cid = STUFF((SELECT ',' + rtrim(cid) FROM t WHERE id = tb.id FOR XML PATH('')) , 1 , 1 , ''),       path = STUFF((SELECT ',' + path FROM t WHERE id = tb.id FOR XML PATH('')) , 1 , 1 , '')from tbgroup by id , nameorder by id/*id   name       cid                                         path---- ---------- ------------------------------------------- ---------------------------------001  广东省     001,002,003,005,006,007,008,009,010,004     广东省,广州市,深圳市,罗湖区,福田区,宝安区,西乡镇,龙华镇,松岗镇,天河区002  广州市     002,004                                     广州市,天河区003  深圳市     003,005,006,007,008,009,010                 深圳市,罗湖区,福田区,宝安区,西乡镇,龙华镇,松岗镇004  天河区     004                                         天河区005  罗湖区     005                                         罗湖区006  福田区     006                                         福田区007  宝安区     007,008,009,010                             宝安区,西乡镇,龙华镇,松岗镇008  西乡镇     008                                         西乡镇009  龙华镇     009                                         龙华镇010  松岗镇     010                                         松岗镇(10 行受影响)*/drop table tb 


[解决办法]

确实有点难。
[解决办法]

SQL code
DECLARE @A INT SET @A=地区IDSELECT COMPANY_NAME,AREA_NAME /*第一级*/FROM COMPANY AJOIN AREA B ON A.AREA_ID=B.AREA_IDWHERE AREA_ID=@AUNION                         /*第二级*/SELECT COMPANY_NAME ,AREA_NAMEFROM COMPANY AJOIN AREA B ON A.AREA_ID=B.AREA_IDWHERE A.AREA_ID IN (SELECT AREA_ID FROM AREA WHERE P_ID=@A)UNION                        /*第三级*/SELECT COMPANY_NAME ,AREA_NAMEFROM COMPANY AJOIN AREA B ON A.AREA_ID=B.AREA_IDWHERE A.AREA_ID IN (SELECT A.AREA_IDFROM AREA AWHERE A.P_ID IN (SELECT AREA_ID FROM AREA WHERE P_ID=@A))...
[解决办法]
如果楼主是2005及高于05的版本,可以运用with cte来解决问题:

SQL code
--company表 (id,parentid,name,...);with cte as(    select * from company where id = ?  --楼主需要查询的目标id    union all    select a.* from company a join cte b on a.parentid = b.id)select *from company a join area b on a.area_name = b.area_name               join cte c on a.id = b.id
[解决办法]
SQL code
-->Title:Generating test data-->Author:wufeng4552-->Date :2009-09-30 08:52:38set nocount onif object_id('tb','U')is not null drop table tbgocreate table tb(ID int, ParentID int)insert into tb select 1,0  insert into tb select 2,1  insert into tb select 3,1  insert into tb select 4,2  insert into tb select 5,3  insert into tb select 6,5  insert into tb select 7,6-->Title:查找指定節點下的子結點if object_id('Uf_GetChildID')is not null drop function Uf_GetChildIDgocreate function Uf_GetChildID(@ParentID int)returns @t table(ID int)asbegin   insert @t select ID from tb where ParentID=@ParentID   while @@rowcount<>0   begin      insert @t select a.ID from tb a inner join @t b      on a.ParentID=b.id and       not exists(select 1 from @t where id=a.id)   end returnendgoselect * from dbo.Uf_GetChildID(5)/*ID-----------67*/-->Title:查找指定節點的所有父結點if object_id('Uf_GetParentID')is not null drop function Uf_GetParentIDgocreate function Uf_GetParentID(@ID int)returns @t table(ParentID int)asbegin   insert @t select ParentID from tb where ID=@ID   while @@rowcount!=0   begin     insert @t select a.ParentID from tb a inner join @t b       on a.id=b.ParentID and        not exists(select 1 from @t where ParentID=a.ParentID)   end  returnendgoselect * from dbo.Uf_GetParentID(2)/*ParentID-----------10*/本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wufeng4552/archive/2009/09/30/4619995.aspx
[解决办法]
SQL code
USE tempdbGO-- 建立演示环境CREATE TABLE Dept( id int PRIMARY KEY,  parent_id int, name nvarchar(20))INSERT DeptSELECT 0, 0, N'<全部>' UNION ALLSELECT 1, 0, N'财务部' UNION ALLSELECT 2, 0, N'行政部' UNION ALLSELECT 3, 0, N'业务部' UNION ALLSELECT 4, 0, N'业务部' UNION ALLSELECT 5, 4, N'销售部' UNION ALLSELECT 6, 4, N'MIS' UNION ALLSELECT 7, 6, N'UI' UNION ALLSELECT 8, 6, N'软件开发' UNION ALLSELECT 9, 8, N'内部开发'GO-- 查询指定部门下面的所有部门DECLARE @Dept_name nvarchar(20)SET @Dept_name = N'MIS';WITHDEPTS AS( -- 定位点成员 SELECT * FROM Dept WHERE name = @Dept_name UNION ALL -- 递归成员, 通过引用CTE自身与Dept基表JOIN实现递归 SELECT A.* FROM Dept A, DEPTS B WHERE A.parent_id = B.id)SELECT * FROM DEPTSGO-- 删除演示环境DROP TABLE Dept
[解决办法]
SQL code
--网吧麽环境,思路create proc calc @id varchar(50)as begin    declare @curr as varchar(1000)    declare @priv as varchar(1000)    set @curr =','+p_id     while @curr <> @priv     begin        select @curr =@curr +id from area where CHARINDEX(p_id,@curr)<>0 and CHARINDEX(id,@curr)=0        set @priv = @curr     end    select * from company inner join (select * from area where CHARINDEX(id,@curr)=0) area         on company.area_id=area.idend 


[解决办法]
-->Title:Generating test data
-->Author:wufeng4552
-->Date :2009-09-30 08:52:38
set nocount on
if object_id('tb','U')is not null drop table tb
go
create table tb(ID int, ParentID int)
insert into tb select 1,0
insert into tb select 2,1
insert into tb select 3,1
insert into tb select 4,2
insert into tb select 5,3
insert into tb select 6,5
insert into tb select 7,6
-->Title:查找指定節點下的子結點
if object_id('Uf_GetChildID')is not null drop function Uf_GetChildID
go
create function Uf_GetChildID(@ParentID int)
returns @t table(ID int)
as
begin
insert @t select ID from tb where ParentID=@ParentID
while @@rowcount<>0
begin
insert @t select a.ID from tb a inner join @t b
on a.ParentID=b.id and 
not exists(select 1 from @t where id=a.id)
end 
return
end
go
select * from dbo.Uf_GetChildID(5)
/*
ID
-----------
6
7
*/
-->Title:查找指定節點的所有父結點
if object_id('Uf_GetParentID')is not null drop function Uf_GetParentID
go
create function Uf_GetParentID(@ID int)
returns @t table(ParentID int)
as
begin
insert @t select ParentID from tb where ID=@ID
while @@rowcount!=0
begin
insert @t select a.ParentID from tb a inner join @t b
on a.id=b.ParentID and 
not exists(select 1 from @t where ParentID=a.ParentID)
end
return
end
go
select * from dbo.Uf_GetParentID(2)
/*
ParentID
-----------
1
0
*/




[解决办法]

SQL code
create proc calc @id varchar(50)as begin    declare @curr as varchar(1000)    declare @priv as varchar(1000)    set @priv=''    set @curr =','+@id     while @curr <> @priv     begin        set @priv = @curr        select @curr =@curr+',' +id from area where CHARINDEX(pid,@curr)<>0 and CHARINDEX(id,@curr)=0    end--    select * from company inner join (    select * from area where CHARINDEX(id,@curr)<>0--) area --        on company.area_id=area.idendgo
[解决办法]
考虑4楼方法吧,不过写法好像有点问题

SQL code
;with cte as(    select * from Area where id = ?  --楼主需要查询的地区id    union all    select a.* from Area a join cte b on a.parentid = b.id)select * --字段自己选择下from company a join cte c on a.Area_id = b.id 

热点排行
Bad Request.