SQL面试题:
把下表中的数据用T-SQL实现效果图。省市县。
答案?
假如你去面试,你去怎么写语句,我想可能每人的思路都不一样。但是肯定会有一种最优的。
不看下文。你先试试你的答案。最好限时、手写哦。
电脑sql编写语句的。下面是测试环境。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
CREATE TABLE [dbo].[area]( [id] [int] NULL, [name] [nvarchar](50) NULL, [par] [int] NULL ) insert area(id,name,par)values(1,'北京',0) insert area(id,name,par)values(2,'河北',0) insert area(id,name,par)values(3,'昌平',1) insert area(id,name,par)values(4,'海淀',1) insert area(id,name,par)values(5,'史各庄',3) insert area(id,name,par)values(6,'回龙观',3) insert area(id,name,par)values(7,'上地',4) insert area(id,name,par)values(8,'西苑',4) insert area(id,name,par)values(9,'石家庄',2) insert area(id,name,par)values(10,'保定',2) uint all insert area(id,name,par)values(11,'桥西区',9) insert area(id,name,par)values(12,'桥东区',9) insert area(id,name,par)values(13,'竞秀区',10) insert area(id,name,par)values(14,'莲池区',10)
思路
刚接手这个的时候蒙圈了。怎么才能第一列是北京 有重复,第二行是第一行的子项。而第三行是第二行的子项。
方案一
最先想到的是UNION ALL把数据堆加起来!
后来一想使用UNION ALL 就必须知道那个是末级,但是我没法直接判断~——放弃。
方案二
使用临时表
脑袋里先有了个大体的思路,先把第一集的取出来。然后存到临时表 #T1。然后根据 #T1的id 找到他的子项(也就是parentId 是 #T1的id的。)然后~依次类推
貌似是可以实现,但是总感觉钻入了一个无底洞。虽然感觉临时表会能解决,但是复杂。考虑到公司不会出太过复杂的答案,应该会有更简单的方案。——放弃
方案三
到现在,这是第一道题,卡主我估计有10几分钟了。越来越着急,后来想,放平时肯定是小case。然后就放松下来。
然后分析效果数据,有数据重复?——连表!
嗯,略微考虑貌似可以。inner 还是 left ?联表肯定是 par 和 id 关联。那就是left。好思路有了。
先一列一列解决,第一列就是 par=0的省级。这好说。
select * from area where par=0
第二步,联表:省级和市级的查询出来。脑海里想想可能执行出的结果是什么结构的。
select * from area T1 left join area T2 on T2.par=T1.id and T1.par=0 where T1.par=0
想象数据结果可能是
/* 北京 昌平 北京 海淀 河北 石家庄 河北 保定 */
然后再次连表,找到县、区 级别的。
逻辑想,只要连表时,取 父级id 是市的。那就先把条件搞定,我要查询所有的市,那就是知道所有的省,直接 par in (所有的省id)
然后写出第三行 子查询
1 select * from area T1 2 left join area T2 on T2.par=T1.id and T1.par=0 3 left join area T3 on T3.par=T2.id and T3.par in (select id from area where par in(select id from area C1 where C1.par=0)) 4 where T1.par=0
结果
直接取T1/T2/T3的name貌似就可以了。
select T1.name as '省',T2.name as '市',T3.name as '县' from area T1 left join area T2 on T2.par=T1.id and T1.par=0 left join area T3 on T3.par=T2.id and T3.par in (select id from area where par in(select id from area C1 where C1.par=0)) where T1.par=0
嗯,没毛病。应该是这样了。
验证结果