数据表结构如下:
no  remain   total   
1     10      20 
2     5       15
3     2       13
5     5       80 
6     10      70
6     20      50
8     40      60
要求把no字段相等或相邻的记录做比较,如果下一条的total+remain=上一条的total则连起来
比如说:
1     10      20 
2     5       15
3     2       13
三条记录,由于No相邻且第二条的15+5等于第一条的20而且第三条的13+2等于第二条的15
所以把第一条和第三条连起来,得出结果:
prior_no    prior_remain   prior_total    next_no   next_remain   next_total
1              10             20            3           2            13
再比如:
5     5       80 
6     10      70
6     20      50
三条纪录,第二条同第一条的no相邻且70+10=80
第三条同第二条的no相等且50+20=70
所以把第一条同第三条连起来,得出结果:
prior_no    prior_remain   prior_total    next_no   next_remain   next_total
5               5             80            6           20           50再看看
8     40      60
这条纪录,由于找不到相符合的纪录,所以就自己同自己连起来
得出结果:
prior_no    prior_remain   prior_total    next_no   next_remain   next_total
8               40            60            8           40           60   ------------------------------------------------------------------------------
最终从这个表中得出结果如下:
prior_no    prior_remain   prior_total    next_no   next_remain   next_total
1              10             20            3           2            13
5               5             80            6           20           50
8               40            60            8           40           60   
------------------------------------------------------------------------------
感觉有点复杂,不知道各位是怎么实现的

解决方案 »

  1.   

    意思是第一条跟第二条比较得出
    prior_no    prior_remain   prior_total    next_no   next_remain   next_total
    1              10             20            3           2            13那第二条不用跟第三条比较??
      

  2.   

    我的方法如果用一条SQL太繁琐,用临时表转一下:
    -------------------------------------------------------------------------------
    declare @t table(no int,remain int,total int)
    insert into @t select 1,10,20 
    insert into @t select 2,5 ,15
    insert into @t select 3,2 ,13
    insert into @t select 5,5 ,80 
    insert into @t select 6,10,70
    insert into @t select 6,20,50
    insert into @t select 8,40,60select identity(int,1,1) as id,* into #1 from @t a where not exists(select 1 from @t where (no=a.no-1 or no=a.no) and total=a.total+a.remain)
    select identity(int,1,1) as id,* into #2 from @t b where not exists(select 1 from @t where (no=b.no+1 or no=b.no) and total+remain=b.total)select a.no prior_no,a.remain prior_remain,a.total prior_total,b.no next_no,b.remain next_remain,b.total next_total from #1 a,#2 b where a.id=b.id/*
    prior_no    prior_remain prior_total next_no     next_remain next_total  
    ----------- ------------ ----------- ----------- ----------- ----------- 
    1           10           20          3           2           13
    5           5            80          6           20          50
    8           40           60          8           40          60
    */drop table #1,#2
      

  3.   

    一定要用一条SQL处理?
    如果不限定实现方式,用游标也可以解决问题。
      

  4.   

    to zlp321002() 
    不连续的就前后笔都是它本身,见上面的第三个举例
      

  5.   

    to coolingpipe(冷箫轻笛)
    第三条当然也要同第二条比较
      

  6.   

    to libin_ftsafe(子陌红尘) 
    不一定要用一条来实现啊,
    这个表有300万条记录,
    只要运行速度不慢就行了
      

  7.   

    -- 测试数据
    DECLARE @t TABLE(no int, remain int, total int)
    INSERT @t SELECT 1,10, 20 
    UNION ALL SELECT 2,5,  15
    UNION ALL SELECT 3,2,  13
    UNION ALL SELECT 5,5,  80 
    UNION ALL SELECT 6,10, 70
    UNION ALL SELECT 6,20, 50
    UNION ALL SELECT 8,40, 60-- 查询
    ;WITH DATA(row, no, remain, total)
    AS(
    SELECT row = ROW_NUMBER() OVER(ORDER BY no), 
    no, remain, total
    FROM @t
    )
    SELECT A.no, A.remain, A.total,
    B.no, B.remain, B.total
    FROM DATA A
    OUTER APPLY(
    SELECT TOP 1 
    AA.no, AA.remain, AA.total 
    FROM DATA AA
    WHERE row >= a.row
    AND NOT EXISTS(
    SELECT * FROM DATA
    WHERE row = AA.row + 1
    AND remain + total = AA.total)
    ORDER BY no) B
    WHERE NOT EXISTS(
    SELECT * FROM DATA
    WHERE row = A.row - 1
    AND A.remain + A.total = total)/*-- 结果
    no          remain      total       no          remain      total
    ----------- ----------- ----------- ----------- ----------- -----------
    1           10          20          3           2           13
    5           5           80          6           20          50
    8           40          60          8           40          60(3 行受影响)
    --*/
      

  8.   

    上面的处理语句适用于sql 2005
      

  9.   

    2000中, 用libin_ftsafe(子陌红尘)的方法, 效率也是不错了.
      

  10.   

    TO zjcxc(邹建),有没有在2000中实现的sql语句
    在2000中用libin_ftsafe(子陌红尘)的方法测试,如果把数据集的顺序打乱,如下:
    declare @t table(no int,remain int,total int)
    insert into @t select 3,2 ,13
    insert into @t select 6,10,70
    insert into @t select 8,40,60
    insert into @t select 1,10,20 
    insert into @t select 2,5 ,15
    insert into @t select 6,20,50
    insert into @t select 5,5 ,80 得出的结果就不正确
    /*
    prior_no    prior_remain prior_total next_no     next_remain next_total  
    ----------- ------------ ----------- ----------- ----------- ----------- 
    8           40           60          3           2           13
    1           10           20          8           40          60
    5           5            80          6           20          50
    */
      

  11.   

    --insert into @t select 8,40,60
    declare @t table(no int,remain int,total int)
    insert into @t select 3,2 ,13
    insert into @t select 6,10,70
    insert into @t select 8,40,60
    insert into @t select 1,10,20 
    insert into @t select 2,5 ,15
    insert into @t select 6,20,50
    insert into @t select 5,5 ,80 
    select identity(int,1,1) as id,* into #1 from @t a 
    where not exists(select 1 from @t where (no=a.no-1 or no=a.no) and total=a.total+a.remain)
    order by noselect identity(int,1,1) as id,* into #2 from @t b 
    where not exists(select 1 from @t where (no=b.no+1 or no=b.no) and total+remain=b.total)
    order by noselect a.no prior_no,a.remain prior_remain,a.total prior_total,b.no next_no,b.remain next_remain,b.total next_total from #1 a,#2 b where a.id=b.id
    DROP TABLE #1, #2-- 结果:
    prior_no prior_remain prior_total next_no next_remain next_total
    1 10 20 3 2 13
    5 5 80 6 20 50
    8 40 60 8 40 60
      

  12.   

    libin_ftsafe(子陌红尘) 的是因为没有加排序, 加了排序就正常了
      

  13.   

    TO:zjcxc(邹建)
    的确no没有重复的话加了排序是没有问题的,可是no并不是唯一的,
    有可能在数据集中存在no重复的
    declare @t table(no int,remain int,total int)
    insert into @t select 3,2 ,13
    insert into @t select 6,10,70
    insert into @t select 8,40,60
    insert into @t select 1,10,20 
    insert into @t select 2,5 ,15
    insert into @t select 6,20,50
    insert into @t select 5,5 ,80 
    insert into @t select 1,100,200--(增加)
    insert into @t select 2,120,80--(增加)select identity(int,1,1) as id,* into #1 from @t a 
    where not exists(select 1 from @t where (no=a.no-1 or no=a.no) and total=a.total+a.remain)
    order by noselect identity(int,1,1) as id,* into #2 from @t b 
    where not exists(select 1 from @t where (no=b.no+1 or no=b.no) and total+remain=b.total)
    order by noselect a.no prior_no,a.remain prior_remain,a.total prior_total,b.no next_no,b.remain next_remain,b.total next_total from #1 a,#2 b where a.id=b.id
    DROP TABLE #1, #2结果也是不正确的,如下:
    /*
    prior_no    prior_remain prior_total next_no     next_remain next_total  
    ----------- ------------ ----------- ----------- ----------- ----------- 
    1           10           20          2           120         80(搭配出错)
    1           100          200         3           2           13(搭配出错)
    5           5            80          6           20          50
    8           40           60          8           40          60
    */
      

  14.   

    重复的NO,怎么确定其顺序?假定这样的情况,肯定无法处理:
    -------------------------------------------------------------------------------------------------------------------------------
    declare @t table(no int,remain int,total int)
    insert into @t select 3,2 ,13
    insert into @t select 6,10,70
    insert into @t select 8,40,60
    insert into @t select 1,10,20--与2可以匹配
    insert into @t select 2,5 ,15
    insert into @t select 6,20,50
    insert into @t select 5,5 ,80 
    insert into @t select 1,20,20--与2可以匹配
      

  15.   

    TO libin_ftsafe(子陌红尘)
    ------------------------------------------
    declare @t table(no int,remain int,total int)
    insert into @t select 1,10,20--与2可以匹配
    insert into @t select 2,5 ,15
    insert into @t select 1,20,20--与2可以匹配
    --------------------------------------------------
    如果出现以上的情况,根据规则那就有2条同2匹配的记录,结果如下:
    /*
    prior_no    prior_remain prior_total next_no     next_remain next_total  
    ----------- ------------ ----------- ----------- ----------- ----------- 
    1           20            20          2           5          15
    1           10            20          2           5          15
    */
    如果是以下这种情况
    ------------------------------------------
    declare @t table(no int,remain int,total int)
    insert into @t select 1,10,20--与2可以匹配
    insert into @t select 2,5 ,15
    insert into @t select 1,20,20--与2可以匹配
    insert into @t select 3,2 ,13
    --------------------------------------------------
    根据规则,结果应为:
    /*
    prior_no    prior_remain prior_total next_no     next_remain next_total  
    ----------- ------------ ----------- ----------- ----------- ----------- 
    1           20            20          3           2          13
    1           10            20          3           2          13
    */
      

  16.   

    to libin_ftsafe(子陌红尘) 
    我觉得按你的方法应该是行不通的。
    因为你的方法没有体现前后笔对应关系的原则,
    只是按数据的顺序来相对应,得出的结果是不准的。数据确实比较复杂,但我总觉得从数据结构的理论上来讲应该是可以实现的,
    可就是不知道如何通过一系列的Sql语句真正的实现
      

  17.   

    如果 libin_ftsafe(子陌红尘) 的方法不行仅在于没有按顺序,同时(假设)插入300万条记录所需时间不长的话,那么可以试试以下方法:
    1.创建一个同构表,将原表中的数据排序后全部插入新表.
    2.按照libin_ftsafe(子陌红尘)的 方法执行.不知道插入300万条记录所需时间长不长,我从来没有试过插入这么多数据,
    如有说错,莫怪:)
      

  18.   

    TO:luckljtchinaren(Lucky) 你可能没有看清楚上面的内容
    libin_ftsafe(子陌红尘)的方法即便是排好序也是行不通的
    因为'NO'字段有可能会存在相同的情况
      

  19.   

    TO geniusli(纠级天使)
    不错,确实是算法方面的问题进行这方面的算法主要原因是为了进行数据分析方面的原因,
    由于在前期设计及各方面人为及设备因素的影响,
    导致'NO'字段值丢失或者重复,因此数据变得相对复杂
    为了能比较直观的分析出表中'NO'字段的哪些值异常(丢失或重复)
    打算用图表的形式来反应上述异常情况,所以才需要这样的结果。
    比如说,如果表中有这么一条记录prior_no    prior_remain prior_total next_no     next_remain next_total  
    ----------- ------------ ----------- ----------- ----------- ----------- 
    1           20            200          100          2          10
    103         100           106          105          2          98则通过图表就是一条由1到100,103到105的两条直线,说明从1到100之间是连续的,103到105也是连续的,就可以看出'NO'为101,102这两条记录丢失不知道我是否表述的清楚。
      

  20.   

    如果原表没有主键则增加一个主键列[id]形成新表,如果已有主键则只需更改以下的id为你的主键列名,以下例子不包括自己连自己的:--insert into @t select 8,40,60
    declare @t table(id int,no int,remain int,total int)
    insert into @t select 1,3,2 ,13
    insert into @t select 2,6,10,70
    insert into @t select 3,8,40,60
    insert into @t select 4,1,10,20 
    insert into @t select 5,2,5 ,15
    insert into @t select 6,6,20,50
    insert into @t select 7,5,5 ,80 
    insert into @t select 8,1,100,200--(增加)
    insert into @t select 9,2,120,80--(增加)select A.no prior_no,A.remain prior_remain,A.total prior_total,D.no next_no,D.remain next_remain,D.total next_total 
    from @t A,@t B,@t D 
    where 
    (A.no=B.no or A.no = B.no-1)  --
    and A.total = B.remain+B.total  --
    and
    (B.no=D.no or B.no = D.no-1)  --
    and B.total = D.remain+D.total  --
    and A.id<>B.id and B.id<>D.id and D.id<>A.id结果为:
    prior_no    prior_remain prior_total next_no     next_remain next_total  
    ----------- ------------ ----------- ----------- ----------- ----------- 
    1           10           20          3           2           13
    5           5            80          6           20          50
      

  21.   

    --如果原表没有主键则增加一个主键列[id]形成新表,如果已有主键则只需更改以下的id为你的主键列名:
    --insert into @t select 8,40,60
    declare @t table(id int,no int,remain int,total int)
    insert into @t select 1,3,2 ,13
    insert into @t select 2,6,10,70
    insert into @t select 3,8,40,60
    insert into @t select 4,1,10,20 
    insert into @t select 5,2,5 ,15
    insert into @t select 6,6,20,50
    insert into @t select 7,5,5 ,80 
    insert into @t select 8,1,100,200--(增加)
    insert into @t select 9,2,120,80--(增加)
    select A.id id1, B.id id2,D.id id3 into #M
    from @t A,@t B,@t D 
    where 
    (A.no=B.no or A.no = B.no-1)  --
    and A.total = B.remain+B.total  --
    and
    (B.no=D.no or B.no = D.no-1)  --
    and B.total = D.remain+D.total  --
    and A.id<>B.id and B.id<>D.id and D.id<>A.idselect id into #P
    from
    (  
    select id1 id from #M
    union
    select id2 id from #M
    union
    select id3 id from #M
    ) Qdrop table #M
    select A.no prior_no,A.remain prior_remain,A.total prior_total,D.no next_no,D.remain next_remain,D.total next_total 
    from @t A,@t B,@t D 
    where 
    (A.no=B.no or A.no = B.no-1)  --
    and A.total = B.remain+B.total  --
    and
    (B.no=D.no or B.no = D.no-1)  --
    and B.total = D.remain+D.total  --
    and A.id<>B.id and B.id<>D.id and D.id<>A.idUNIONselect A.no prior_no,A.remain prior_remain,A.total prior_total,A.no next_no,A.remain next_remain,A.total next_total 
    from @t A
    where
    A.id not in (select id from #P)drop table #P
    结果:
    prior_no    prior_remain prior_total next_no     next_remain next_total  
    ----------- ------------ ----------- ----------- ----------- ----------- 
    1           10           20          3           2           13
    1           100          200         1           100         200
    2           120          80          2           120         80
    5           5            80          6           20          50
    8           40           60          8           40          60好像比较长的样子哦,不知道有没有错...
      

  22.   

    to:luckljtchinaren(Lucky)
    你是算法有问题,你试试declare @t table(id int,no int,remain int,total int)
    insert into @t select 1,3,2 ,13
    insert into @t select 2,6,10,70
    insert into @t select 3,8,40,60
    insert into @t select 4,1,10,20 
    insert into @t select 5,2,5 ,15
    --insert into @t select 6,6,20,50(删除掉这条记录)
    insert into @t select 7,5,5 ,80 
    insert into @t select 8,1,100,200--(增加)
    insert into @t select 9,2,120,80--(增加)不包括自己连自己的,得出结果为:
    /*
    prior_no    prior_remain prior_total next_no     next_remain next_total  
    ----------- ------------ ----------- ----------- ----------- ----------- 
    1           10           20          3           2           13
    */
    正确的应该为:
    prior_no    prior_remain prior_total next_no     next_remain next_total  
    ----------- ------------ ----------- ----------- ----------- ----------- 
    1           10           20          3           2           13
    5           5            80          6          10           70
      

  23.   

    照你在题目开头所说的:
    5     5       80 
    6     10      70
    6     20      50这三条记录得到一条记录
    prior_no    prior_remain   prior_total    next_no   next_remain   next_total
    5               5             80            6           20           50但是你不是将删除掉了其中的一行吗:--insert into @t select 6,6,20,50(删除掉这条记录);
    所以剩下的:
    5     5       80 
    6     10      70
    没有第三条记录与"6,10,70"相连,只能是自己连自己的了。不知道有没有说错?
      

  24.   

    to:luckljtchinaren(Lucky)
    5     5       80 
    6     10      70
    没有第三条记录与"6,10,70"相连,只能是自己连自己的了。不知道有没有说错?
    ------------------------------------------------------------------------
    这两条记录是可以相连的,
    应该为:
    5     5       80     6     10      70
    为什么只能是自己连自己呢?
      

  25.   

    to:luckljtchinaren(Lucky)
    你可能误解我的意思了
    不仅仅只是三条记录相连,有可能是更多,比如5条:
    declare @t table(no int,remain int,total int)
    insert into @t select 1,10,20 
    insert into @t select 2,5 ,15
    insert into @t select 3,2 ,13
    insert into @t select 4,2 ,11
    insert into @t select 5,5 ,6 
    形成记录应如下:
    prior_no    prior_remain   prior_total    next_no   next_remain   next_total
    1             10               20            5            5            6
      

  26.   

    问题一:
    数据如下:
    no  remain   total   
    1     10      20 
    2     5       15
    3     2       13
    5     5       80 
    6     10      70
    6     20      50
    8     40      60
    那么它的顺序是确定的,比如no为6的那两条数据是不能互换的,也就是说它们如果排序的话是按no再按remain最后按total进行升序。问这个问题的原因是,只有输入确定,输出才有正确的结果。问题二:
    对于这样的数据:
    1     10      20 
    2     5       15
    3     2       13
    所得到的最终结果是什么样的情况,有两种情况
    第一种就是只有一条结果
    1     10      20      3     2       13
    第二种情况是有两条结果
    1     10      20      3     2       13
    2     5       15      3     2       13
    这两种结果的区别在于,第一种没有处理区间内部的数据,而第二种对区间内部连续数据又进行了一次运算。