一些比较难的sql问题:4

2014-11-24 14:09:59 · 作者: · 浏览: 0
一些比较难的sql问题:4
最近,在 论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了。
所以,觉得有必要记录下来,这样以后再次碰到这类问题,也能从中获取解答的思路。
1、求一个获取连续值的方法。
这个用spt_values也可以。
如果是SQL Server 2005及以后的版本,可以通过递归来实现,非常简单。
我的解法:
[sql] 
;with r  
as  
(  
select 1 as number   --第一个数  
  
union all  
  
select number + 1  
from r  
where r.number < 10 --最后一个数  
)  
  
select *  
from r  
--option(maxrecursion 1000)  
/*  
number  
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
*/  

2、如何去掉字段内的重复。
不是去整行,行都是唯一的,如,现有下表:
零件号 名称 装入上级 装入数量 总数量
TI4.005 A AA 1 1
TI4.005 A BB 1 1
TI4.005 A CC 2 2
TI4.005 4
希望得到的结果:
TI4.005 A AA 1 1
BB 1 1
CC 2 2
4
如何用sql实现?
我的解法,不过这个解法需要数据是按照一定的顺序输入的,因为语句中只查找上一行的数据,和上一行进行比较,如果没有顺序,可能会有问题:
[sql] 
;with t(零件号,      名称,   装入上级 ,  装入数量,  总数量)  
as  
(  
select 'TI4.005',    'A',     'AA',          1,       1 union all  
select 'TI4.005',    'A',     'BB',          1,       1 union all  
select 'TI4.005',    'A',     'CC',          2,       2 union all  
select 'TI4.005',    null,      null,        null,    4   
),  
  
tt  
as  
(  
select *,  
       row_number() over(partition by 零件号 order by 零件号) as rownum  
from t  
)  
  
  
select case when 零件号 = (select top 1 零件号 from tt t2   
                           where t1.零件号 = t2.零件号  
                                 and t2.rownum < t1.rownum   
                           order by t2.rownum desc)  
                  then null  
            else 零件号  
       end as 零件号,  
         
       case when 名称 = (select top 1 名称 from tt t2   
                           where t1.零件号 = t2.零件号  
                                 and t2.rownum < t1.rownum   
                           order by t2.rownum desc)  
                  then null  
            else 名称  
       end as 名称,  
         
       case when 装入上级 = (select top 1 名称 from tt t2   
                           where t1.零件号 = t2.零件号  
                                 and t2.rownum < t1.rownum   
                           order by t2.rownum desc)  
                  then null  
            else 装入上级  
       end as 装入上级,  
         
       装入数量,  
       总数量   
from tt t1  
/*  
零件号 名称      装入上级    装入数量    总数量  
TI4.005 A       AA          1           1  
NULL    NULL        BB          1           1  
NULL    NULL        CC          2           2  
NULL    NULL        NULL    NULL            4  
*/  

3、求sql,看似简单。
No FLAG
1 Z
2 Z
3 Z
4 L
5 Z
6 L
7 L
8 L
查询结果
FLAG-Z FLAG-L
1 4
2 6
3 7
4 8
SQL2000 数据库
我的解法,最关键的是如何生成行号,分别对不同的数据产生行号,由于是2000数据库,稍微有点麻烦:
[sql] 
drop table t  
  
create table t(No int,FLAG varchar(10));  
  
insert into t  
select 1        ,   'Z' union all       
select 2        ,   'Z' union all           
select 3        ,   'Z' union all  
select 4        ,   'L' union all           
select 5        ,   'Z' union all           
select 6        ,   'L' union all           
select 7        ,   'L' union all           
select 8        ,   'L'  
  
select z.no,L.no  
from   
(  
select *,  
       (select count(*) from t t2 where t2.no <= t1.no and t2.flag = 'z') as rownum  
from t t1  
where flag = 'z'  
)z  
inner join   
(  
select *,  
       (select count(*) from t t2 where t2.no <= t1.no and t2.flag = 'L') as rownum  
from t t1  
where flag = 'L'  
)L  
 on z.rownum = L.rownum  
/*  
no  no  
1   4  
2   6  
3   7  
5   8  
*/  

如果是2005数据库,那么就简单多了:
[sql] 
drop table t  
  
create table t(No int,FLAG varchar(10));  
  
insert into t  
select 1        ,   'Z' union all       
select 2        ,   'Z' union all           
select 3        ,   'Z' union all  
select 4        ,   'L' union all           
select 5        ,   'Z' union all           
select 6        ,   'L' union all           
select 7        ,   'L' union all           
select 8        ,   'L'  
  
select t1.no,t2.no  
from   
(  
select *,  
       row_number() over(partition by flag order by no) as rownum   
from t  
)t1  
inner join   
(  
select *,  
       row_number() over(partition by flag order by no) as rownum   
from t  
)t2  
on t1.rownum = t2.rownum  
   and t1.flag = 'z'  
   and t2.flag = 'L'  
  
/*  
no  no  
1   4  
2   6  
3   7  
5   8  
*/