高手请进
数据库中有如下记录
ip1 ip2 country
0 2 美国
3 9 中国
10 18 美国
19 20 美国
21 30 美国
31 33 中国
34 34 中国
35 36 中国
37 38 英国
39 40 英国
如何获得如下记录
ip1 ip2 country
0 2 美国
3 9 中国
10 30 美国
31 36 中国
37 40 英国
记录大约有15万
请指点
问题点数:20、回复次数:15Top
1 楼LouisXIV(夜游神)回复于 2006-07-01 11:02:08 得分 0
这种需要遍历的查询,15w条速度很难上去Top
2 楼wwh999(印钞机V2.0...开发中....)回复于 2006-07-01 11:34:56 得分 0
--生成测试数据
Declare @t table(IP1 int,IP2 int,Country varchar(10))
INSERT INTO @t SELECT 0,2,'美国'
UNION ALL SELECT 3 ,9, '中国'
UNION ALL SELECT 10,18,'美国'
UNION ALL SELECT 19,20,'美国'
UNION ALL SELECT 21,30,'美国'
UNION ALL SELECT 31,33,'中国'
UNION ALL SELECT 34,34,'中国'
UNION ALL SELECT 35,36,'中国'
UNION ALL SELECT 37,38,'英国'
UNION ALL SELECT 39,40,'英国'
--生成临时表便于分组操作
select ID=Identity(int,1,1),* into #temp from @t
SELECT * from #Temp
GO
--起作用的SELECT
select IP1=MIN(B.IP1),IP2=MAX(B.IP2),COUNTRY
from
(select ID,IP1,IP2,COUNTRY,辅助分组列=(select MIN(ID) from #Temp where ID>A.id and Country!=A.Country)
FROM #Temp A
)B
Group by Country,辅助分组列
Order by IP1
GO
Drop Table #Temp
Top
3 楼wwh999(印钞机V2.0...开发中....)回复于 2006-07-01 11:36:42 得分 0
/*-- 结果
IP1 IP2 COUNTRY
----------- ----------- ----------
0 2 美国
3 9 中国
10 30 美国
31 36 中国
37 40 英国
(所影响的行数为 5 行)
-- */ --完成Top
4 楼wwh999(印钞机V2.0...开发中....)回复于 2006-07-01 11:37:18 得分 0
晕,这题用了半个小时....汗!Top
5 楼LouisXIV(夜游神)回复于 2006-07-01 11:40:49 得分 0
效率上不去:)Top
6 楼wwh999(印钞机V2.0...开发中....)回复于 2006-07-01 11:44:16 得分 0
这样的要求,本来就是不能指望效率的....Top
7 楼hellowork(一两清风)回复于 2006-07-01 14:36:32 得分 0
楼主没有说明ip1和ip2列的值是否都是递增的,如果是无规律的,而是完全基于物理行的话,max()和min()就不能作为筛选依据了,需要使用静态游标遍历.以下是此种情况下的代码:
----创建测试数据表变量
declare @t table(ip1 int,ip2 int,country varchar(10))
insert @t
select 0,2,'美国' union
select 3,9,'中国' union
select 10,18,'美国' union
select 19,20,'美国' union
select 21,30,'美国' union
select 31,33,'中国' union
select 34,34,'中国' union
select 35,36,'中国' union
select 37,38,'英国' union
select 39,40,'英国'
select * from @t
----声明变量
declare @ip1 int
declare @ip2 int
declare @Country varchar(10)
declare @Startip1 int /*段起始行的IP1列值*/
declare @Endip2 int /*段截止行的IP2列值*/
declare @StartCountry varchar(10) /*段起始行的COUNTRY列值*/
set @StartCountry = '' /*初始化,作为游标第一行的判断依据*/
declare @tab table(ip1 int,ip2 int,country varchar(10)) /*保存符合条件的行的临时表变量*/
declare cur cursor STATIC READ_ONLY for select ip1,ip2,country from @t /*创建静态游标*/
open cur
if @@CURSOR_ROWS > 0
BEGIN
fetch next from cur into @ip1,@ip2,@Country /*提取游标行到变量中*/
WHILE @@fetch_status = 0
Begin
if @StartCountry = '' /*如果是游标第一行*/
Begin
set @Startip1 = @ip1 /*记录段起始行的IP1列值*/
set @Endip2 = @ip2 /*记录段起始行的IP2列值*/
set @StartCountry = @Country /*记录段起始行的COUNTRY列值*/
End
else /*如果不是游标第一行*/
Begin
if @StartCountry <> @Country /*如果当前行是新段的开始*/
Begin
insert @tab select @Startip1,@Endip2,@StartCountry /*保存符合条件的行*/
set @Startip1 = @ip1 /*记录新段起始行的IP1列值*/
set @Endip2 = @ip2 /*记录新段起始行的IP2列值*/
set @StartCountry = @Country /*记录新段起始行的COUNTRY列值*/
End
else /*当前行是同段内的行*/
set @Endip2 = @ip2 /*记录当前行的IP2列值,作为当前段最后一行的IP2列值*/
fetch next from cur into @ip1,@ip2,@Country /*提取下一行*/
End
End
insert @tab select @Startip1,@Endip2,@StartCountry /*游标最后一行作为上个段的截止行*/
close cur
deallocate cur
END
----查看结果
select * from @tabTop
8 楼wwh999(印钞机V2.0...开发中....)回复于 2006-07-01 14:43:31 得分 0
TO hellowork()
楼主没有说明ip1和ip2列的值是否都是递增的,如果是无规律的,而是完全基于物理行的话,max()和min()就不能作为筛选依据了,需要使用静态游标遍历.以下是此种情况下的代码:
------------------------------------------------------------------------------------
拜托你看清楚一些...,我上面的代码中已经做了处理的.会为其生成自增列...
select ID=Identity(int,1,1),* into #temp from @t
我看了一下你的代码,你上面又用游标,有用循环...效率很低!应尽量避免使用游标!Top
9 楼fcuandy(了此残生.)回复于 2006-07-01 14:57:10 得分 0
用臨時表,然後利用IDENTITY生成的ID,進行JOIN來比較數據的連續性,我經常用這種方法.
這種方法用熟了,在這三兩個星期,用這種方法寫過四五個了.
http://community.csdn.net/Expert/topic/4809/4809172.xml?temp=.8137018
http://community.csdn.net/Expert/topic/4851/4851296.xml?temp=.5042536
下面這個是由COUNT出递增的ID,因为他原表有主健.
http://community.csdn.net/Expert/topic/4850/4850455.xml?temp=9.740847E-02
...Top
10 楼hellowork(一两清风)回复于 2006-07-01 15:13:44 得分 0
多谢楼上wwh999(印钞机V2.0...开发中....)朋友的提醒,我的想法只是在表中没有IDENTITY列并且不想重建IDENTITY列时的解决办法,只是在为楼主提供另外的参考方法,让楼主多一种选择,不是比较算法,仅此而已.
select ID=Identity(int,1,1),* into #temp from @t也会花费时间提取所有行,并为每行计算生成ID.
如果楼主的表中直接就有IDENTITY列就好了.Top
11 楼fcuandy(了此残生.)回复于 2006-07-01 15:17:18 得分 0
樓主表中如果有identity列,那麼因為由于值可能不連續,所以也不能直接用.
還是需要使用臨時表, 或用COUNT生成新列.
要比較記錄值的連續性,需要依靠連續的ID(值連續的列),不連續的話,連接條件無法确定.Top
12 楼hellowork(一两清风)回复于 2006-07-01 15:20:42 得分 0
多谢楼上的二位朋友的指教!Top
13 楼fcuandy(了此残生.)回复于 2006-07-01 15:47:15 得分 0
大家一起讨论Top
14 楼t122()回复于 2007-04-25 15:52:52 得分 0
还有谁有高见?Top
15 楼fanmb(我要努力)回复于 2007-04-26 09:45:02 得分 0
select ip1,max(ip2) as ip2,country from tb1 group by ip1,countryTop




