CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
不看会后悔的Windows XP之经验谈 简单快捷DIY实用家庭影院
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  MS-SQL Server >  基础类

高手请进

楼主t122()2006-07-01 10:46:34 在 MS-SQL Server / 基础类 提问

数据库中有如下记录  
  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

相关问题

关键词

得分解答快速导航

  • 帖主:t122

相关链接

  • SQL Server类图书

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo