最近,在论坛中,遇到了不少比较难的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