在论坛中出现的比较难的sql问题:3(row_number函数 分组查询)

最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了。

所以,觉得有必要记录下来,这样以后再次碰到这类问题,也能从中获取解答的思路。另外,考虑到前2篇太长,看起来不太方便,所以拆分为第3篇



1、分组查询问题

http://bbs.csdn.net/topics/390619682?page=1#post-395835328

例子表结构数据如下:
id status date        price
1  1      2013-10-01  218
2  1      2013-10-02  218
3  0      2013-10-03  218
4  0      2013-10-04  238
5  0      2013-10-05  238
6  0      2013-10-06  238
7  0      2013-10-07  258
8  0      2013-10-08  258
9  0      2013-10-09  218


想获取的结果集一:
2013-10-01至2013-10-03  218
2013-10-04至2013-10-06  238
2013-10-07至2013-10-08  258
2013-10-09至2013-10-09  218


想获取的结果集二:
1  2013-10-01至2013-10-02  218
0  2013-10-03至2013-10-03  218
0  2013-10-04至2013-10-06  238
0  2013-10-07至2013-10-08  258
0  2013-10-09至2013-10-09  218


我的解法:

--drop table tb

create table tb(id int,status int,date varchar(10),price int)

insert into tb
select 1,  1,      '2013-10-01',  218 union all
select 2,  1,      '2013-10-02',  218 union all
select 3,  0,      '2013-10-03',  218 union all
select 4,  0,      '2013-10-04',  238 union all
select 5,  0,      '2013-10-05',  238 union all
select 6,  0,      '2013-10-06',  238 union all
select 7,  0,      '2013-10-07',  258 union all
select 8,  0,      '2013-10-08',  258 union all
select 9,  0,      '2013-10-09',  218 --union all
--select 10,  0,      '2013-10-10',  218 
go



--第一个结果集
;with t
as
(
select *,
       row_number() over(partition by price order by id) as rownum,
       min(id) over(partition by price) as min_id
from tb 
),

tt
as
(
select id,
       price,
       a.date,
       rownum - (id - min_id) as interval
from t a 
)

select min(date) + '至' + max(date) as date,
       price
from tt
group by price,interval
order by 1
/*
date	                price
2013-10-01至2013-10-03	218
2013-10-04至2013-10-06	238
2013-10-07至2013-10-08	258
2013-10-09至2013-10-09	218
*/


--第2个结果集
;with t
as
(
select *,
       row_number() over(partition by status,price order by id) as rownum,
       min(id) over(partition by status,price) as min_id
from tb 
),

tt
as
(
select id,
       price,
       a.date,
       a.status,
       rownum - (id - min_id) as interval
from t a 
)

select status,min(date) + '至' + max(date),price
from tt
group by status,price,interval
order by 2
/*
status date	                    price
1	   2013-10-01至2013-10-02	218
0	   2013-10-03至2013-10-03	218
0	   2013-10-04至2013-10-06	238
0	   2013-10-07至2013-10-08	258
0	   2013-10-09至2013-10-09	218
*/


2、查询出一段数据后判断记录里面的最大id,是否大于值a 查询语句如下:
http://bbs.csdn.net/topics/390619191
select top 200 id, ClassId,Name,Price,BoxContain,BoxLength,BoxWidth,BoxHeight,CName,EName,CPack,PhotoFolder,EPack,0.46*(round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3))*35.32/BoxContain+Price/6*1.08 from ProductData where ClassId=101 and BoxContain >0 and BoxContain is not null and round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3) >=0 And round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3) <= 10000 and (0.46*(round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3))*35.32/BoxContain+Price/6*1.08) >=10 and (0.46*(round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3))*35.32/BoxContain+Price/6*1.08) <=1000 and EPack='Window Box' order by id asc

我的解法,适用于SQL Server 2000:

select *
from 
(
select top 200 id, ClassId,Name,Price,BoxContain,BoxLength,BoxWidth,BoxHeight,CName,EName,CPack,PhotoFolder,EPack,
0.46*(round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3))*35.32/BoxContain+Price/6*1.08 
from ProductData 
where ClassId=101 and BoxContain >0 and BoxContain is not null 
and round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3) >=0
 And round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3) <= 10000 
 and (0.46*(round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3))*35.32/BoxContain+Price/6*1.08) >=10 
 and (0.46*(round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3))*35.32/BoxContain+Price/6*1.08) <=1000 
 and EPack='Window Box' 
order by id asc
)t
where
(
	select max(id) 
    from
	(
	select top 200 id, ClassId,Name,Price,BoxContain,BoxLength,BoxWidth,BoxHeight,CName,EName,CPack,PhotoFolder,EPack,
	0.46*(round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3))*35.32/BoxContain+Price/6*1.08 
	from ProductData 
	where ClassId=101 and BoxContain >0 and BoxContain is not null 
	and round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3) >=0
	 And round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3) <= 10000 
	 and (0.46*(round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3))*35.32/BoxContain+Price/6*1.08) >=10 
	 and (0.46*(round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3))*35.32/BoxContain+Price/6*1.08) <=1000 
	 and EPack='Window Box' 
         order by id asc
	)t
) > a


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值