怎么这么慢?

shadow110112 2009-08-17 10:34:14
我的问题是:
编号,开始时间,结束时间,类别
1,2009-7-1,2009-10-1,ee
1,2009-7-2,2009-10-20,tt
2,2009-7-3,2009-9-5,uu
2,2009-7-4,NULL,tt
2,2009-7-5,NULL,ii
3,2009-7-6,2009-10-8,ii
3,2009-7-7,2009-10-8,oo
.................
这样的SQL语句:
1、当编号中结束时间有NULL字段的,要是NULL有多个时,从有NULL的数据中选择开始时间最小的,如上面的编号2,则选2009-7-4
否则就选NULL的哪个
2,当编号中结束时间没有NULL字段时,则选结束时间最大的,结束时间可能是有重复的,则选任意一个就可以如3,
如上面的例子的结果:
1,2009-7-2,2009-10-20,tt
2,2009-7-4,NULL,tt
3,2009-7-6,2009-10-8,ii
....
这样的SQL语句怎么写啊?
答案是:
IF OBJECT_ID('tb') IS NOT NULL
DROP TABLE tb
GO
CREATE TABLE tb( 编号 int,开始时间 varchar(10),结束时间 varchar(10) ,类别 varchar(10) )
go
insert tb SELECT
1,'2009-7-1','2009-10-1','ee' UNION ALL SELECT
1,'2009-7-2','2009-10-20','tt' UNION ALL SELECT
2,'2009-7-3','2009-9-5','uu' UNION ALL SELECT
2,'2009-7-4',NULL,'tt' UNION ALL SELECT
2,'2009-7-5',NULL,'ii' UNION ALL SELECT
3,'2009-7-6','2009-10-8','ii' UNION ALL SELECT
3,'2009-7-7','2009-10-8','oo'
go
select * from(
select *
from tb t
where 结束时间 is null and not exists(select * from tb where 编号=t.编号 and 结束时间 is null and 开始时间<t.开始时间)
union all
select *
from tb t
where 编号 not in (select 编号 from tb where 结束时间 is null)
and not exists(select * from tb where 编号=t.编号 and (结束时间>t.结束时间 or 结束时间=t.结束时间 and 开始时间>t.开始时间))) k
order by 编号
但是数据库中有二三十万的记录的时候很慢啊,都显示不出来,这是为什么呢,还有没有更好的解决办法呢?
...全文
170 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
xupeihuagudulei 2009-08-31
  • 打赏
  • 举报
回复
再顶一次,这帖子我看了好久,
可是我却发表不了评论。
哎,
就等着牛人回答吧
xupeihuagudulei 2009-08-31
  • 打赏
  • 举报
回复
狂顶
jie810516 2009-08-30
  • 打赏
  • 举报
回复
---tb表建立索引
create index tb_index on tb(编号)

----找出结束时间为null的每个编号的最小开始时间,生成临时表#a
select 编号,min(开始时间) 开始时间 into #a from tb where 结束时间 is null group by 编号

create index a_index on #a(编号)

----根据#a找出结束时间为null的相关数据
select a.编号,a.开始时间,a.结束时间,min(a.类别) 类别 into #aa from tb a,#a b
where a.编号=b.编号 and a.开始时间=b.开始时间
group by a.编号,a.开始时间,a.结束时间

----选择出结束时间不为null的数据,生成临时表#b
select 编号,max(结束时间) 结束时间 into #b from tb where 编号 not in (select 编号 from #a) group by 编号

create index b_index on #b(编号)

---根据#b找出结束时间不为null的相关数据
select c.编号,c.开始时间,c.结束时间,min(类别) 类别 into #bb from
(select a.编号,min(a.开始时间) 开始时间,a.结束时间 from tb a,#b b
where a.编号=b.编号 and a.结束时间=b.结束时间
group by a.编号,a.结束时间) c,tb d
where c.编号=d.编号 and c.开始时间=d.开始时间 and c.结束时间=d.结束时间

drop table #a
drop table #b

----结果
select 编号,开始时间,结束时间,类别 from #aa
union all
select 编号,开始时间,结束时间,类别 from #bb
order by 1












shadow110112 2009-08-25
  • 打赏
  • 举报
回复
能不能写全出来啊?
shadow110112 2009-08-17
  • 打赏
  • 举报
回复
呵呵,真不好意思,可能是我没有说明白了.我的条件是:
1、当编号中结束时间有NULL字段的,要是NULL有多个时,从有NULL的数据中选择开始时间最小的,如上面的编号2,
2,2009-7-3,2009-9-5,uu
2,2009-7-4,NULL,tt
2,2009-7-5,NULL,ii
结束时间有NULL也有不是NULL的,这样的情况就选结束时间是NULL的,有多个的时候选开始时间最小的那个.等到的结果是:
2,2009-7-4,NULL,tt
2,当编号中结束时间没有NULL字段时,则选结束时间最大的,结束时间可能是有重复的,则选任意一个就可以如3,
3,2009-7-6,2009-10-8,ii
3,2009-7-7,2009-10-8,oo
结束时间里没有NULL的,选结束时间最大的就可以了.
如上面的例子的结果:
1,2009-7-2,2009-10-20,tt
2,2009-7-4,NULL,tt
3,2009-7-6,2009-10-8,ii
这样不知道能不能看明白?
SQL77 2009-08-17
  • 打赏
  • 举报
回复
楼主加上索引试试?
SQL77 2009-08-17
  • 打赏
  • 举报
回复
IF OBJECT_ID('tb') IS NOT NULL 
DROP TABLE tb
GO
CREATE TABLE tb( 编号 int,开始时间 varchar(10),结束时间 varchar(10) ,类别 varchar(10) )
go
insert tb SELECT
1,'2009-7-1','2009-10-1','ee' UNION ALL SELECT
1,'2009-7-2','2009-10-20','tt' UNION ALL SELECT
2,'2009-7-3','2009-9-5','uu' UNION ALL SELECT
2,'2009-7-4',NULL,'tt' UNION ALL SELECT
2,'2009-7-5',NULL,'ii' UNION ALL SELECT
3,'2009-7-6','2009-10-8','ii' UNION ALL SELECT
3,'2009-7-7','2009-10-8','oo'
go

select t.* from tb t ,
(SELECT 编号,min(开始时间)开始时间 FROM TB T WHERE 结束时间 IS NULL group by 编号)as t1
where t.编号=t1.编号 and t.开始时间=t1.开始时间

UNION ALL

SELECT * FROM TB T WHERE
开始时间=(SELECT MAX(开始时间) FROM TB WHERE 编号=T.编号)
and 编号 not in
(SELECT 编号 FROM TB T WHERE 结束时间 IS NULL)

order by t.编号

编号 开始时间 结束时间 类别
----------- ---------- ---------- ----------
1 2009-7-2 2009-10-20 tt
2 2009-7-4 NULL tt
3 2009-7-7 2009-10-8 oo

(所影响的行数为 3 行)


终于理解楼主的需求了
SQL77 2009-08-17
  • 打赏
  • 举报
回复
IF OBJECT_ID('tb') IS NOT NULL 
DROP TABLE tb
GO
CREATE TABLE tb( 编号 int,开始时间 varchar(10),结束时间 varchar(10) ,类别 varchar(10) )
go
insert tb SELECT
1,'2009-7-1','2009-10-1','ee' UNION ALL SELECT
1,'2009-7-2','2009-10-20','tt' UNION ALL SELECT
2,'2009-7-3','2009-9-5','uu' UNION ALL SELECT
2,'2009-7-4',NULL,'tt' UNION ALL SELECT
2,'2009-7-5',NULL,'ii' UNION ALL SELECT
3,'2009-7-6','2009-10-8','ii' UNION ALL SELECT
3,'2009-7-7','2009-10-8','oo'
go

select t.* from tb t ,
(SELECT 编号,min(开始时间)开始时间 FROM TB T WHERE 结束时间 IS NULL group by 编号)as t1
where t.编号=t1.编号 and t.开始时间=t1.开始时间

UNION ALL

SELECT * FROM TB T WHERE
开始时间=(SELECT MAX(开始时间) FROM TB WHERE 编号=T.编号 AND 结束时间 IS NOT NULL )

编号 开始时间 结束时间 类别
----------- ---------- ---------- ----------
2 2009-7-4 NULL tt
1 2009-7-2 2009-10-20 tt
2 2009-7-3 2009-9-5 uu
3 2009-7-7 2009-10-8 oo

(所影响的行数为 4 行)

理解错误了,呵呵这样应该行了
shadow110112 2009-08-17
  • 打赏
  • 举报
回复
怎么有重复的啊。我的要求是这样的:
编号,开始时间,结束时间,类别
1,2009-7-1,2009-10-1,ee
1,2009-7-2,2009-10-20,tt
2,2009-7-3,2009-9-5,uu
2,2009-7-4,NULL,tt
2,2009-7-5,NULL,ii
3,2009-7-6,2009-10-8,ii
3,2009-7-7,2009-10-8,oo
.................
这样的SQL语句:
1、当编号中结束时间有NULL字段的,要是NULL有多个时,从有NULL的数据中选择开始时间最小的,如上面的编号2,则选2009-7-4
否则就选NULL的哪个
2,当编号中结束时间没有NULL字段时,则选结束时间最大的,结束时间可能是有重复的,则选任意一个就可以如3,
如上面的例子的结果:
1,2009-7-2,2009-10-20,tt
2,2009-7-4,NULL,tt
3,2009-7-6,2009-10-8,ii
....

SQL77 2009-08-17
  • 打赏
  • 举报
回复
IF OBJECT_ID('tb') IS NOT NULL 
DROP TABLE tb
GO
CREATE TABLE tb( 编号 int,开始时间 varchar(10),结束时间 varchar(10) ,类别 varchar(10) )
go
insert tb SELECT
1,'2009-7-1','2009-10-1','ee' UNION ALL SELECT
1,'2009-7-2','2009-10-20','tt' UNION ALL SELECT
2,'2009-7-3','2009-9-5','uu' UNION ALL SELECT
2,'2009-7-4',NULL,'tt' UNION ALL SELECT
2,'2009-7-5',NULL,'ii' UNION ALL SELECT
3,'2009-7-6','2009-10-8','ii' UNION ALL SELECT
3,'2009-7-7','2009-10-8','oo'
go

select t.* from tb t ,
(SELECT 编号,min(开始时间)开始时间 FROM TB T WHERE 结束时间 IS NULL group by 编号)as t1
where t.编号=t1.编号 and t.开始时间=t1.开始时间

UNION ALL

SELECT * FROM TB T WHERE
开始时间=(SELECT MAX(开始时间) FROM TB WHERE 编号=T.编号 AND 结束时间=T.结束时间 AND 结束时间 IS NOT NULL )
编号 开始时间 结束时间 类别
----------- ---------- ---------- ----------
2 2009-7-4 NULL tt
3 2009-7-7 2009-10-8 oo
2 2009-7-3 2009-9-5 uu
1 2009-7-2 2009-10-20 tt
1 2009-7-1 2009-10-1 ee

(所影响的行数为 5 行)
shadow110112 2009-08-17
  • 打赏
  • 举报
回复
你这样改了是快了很多,但是数据不对啊,有的没有显示出来
SQL77 2009-08-17
  • 打赏
  • 举报
回复
SELECT * FROM TB T WHERE 
开始时间=(SELECT MIN(开始时间) FROM TB WHERE 编号=T.编号 AND 结束时间=T.结束时间 AND 结束时间 IS NULL )

UNION ALL

SELECT * FROM TB T WHERE
开始时间=(SELECT MAX(开始时间) FROM TB WHERE 编号=T.编号 AND 结束时间=T.结束时间 AND 结束时间 IS NOT NULL )


看了下楼主的要求,这个试试行不行
shadow110112 2009-08-17
  • 打赏
  • 举报
回复
还是不行啊,郁闷了.
SQL77 2009-08-17
  • 打赏
  • 举报
回复
结束时间>t.结束时间 or 结束时间=t.结束时间 and 开始时间>t.开始时间

--->结束时间>=t.结束时间 and 开始时间>t.开始时间
--小F-- 2009-08-17
  • 打赏
  • 举报
回复
加索引吧
SQL77 2009-08-17
  • 打赏
  • 举报
回复
加索引试试
SQL77 2009-08-17
  • 打赏
  • 举报
回复
CREATE CLUSTERED INDEX Idx1 ON TB (编号)
shadow110112 2009-08-17
  • 打赏
  • 举报
回复
呵呵,怎么加进去啊?
SQL77 2009-08-17
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 shadow110112 的回复:]
这样是达到我的要求了,但是时间还是有点长,在SQL2000里运行都要一分多钟了,用程序操作这个存储过程的时候就提示超时了.还有没有更快啊,我都已经把数据连接的connect timeout=200调到这了,还是提示超时啊,晕了
[/Quote]
楼主的要求好难达到,加索引试试看能不能快点
shadow110112 2009-08-17
  • 打赏
  • 举报
回复
这样是达到我的要求了,但是时间还是有点长,在SQL2000里运行都要一分多钟了,用程序操作这个存储过程的时候就提示超时了.还有没有更快啊,我都已经把数据连接的connect timeout=200调到这了,还是提示超时啊,晕了
加载更多回复(8)

27,579

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 应用实例
社区管理员
  • 应用实例社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧