挑战:SQL检查下一条记录与之前的对比

时间:2010-08-03 06:53:38

标签: sql

我有一些需要验证的数据,虽然我找到了一个在excel中运行的快速公式,但我想找到一些可以做同样的SQL,所以我可以在我的数据库中使用它作为支票现在和然后

数据就是这样:

ACACIA ST (KLN) | 1073 | 1149 | FAIL! | 76
ACACIA ST (KLN) | 1073 | 1151 | FAIL! | 78
ACACIA ST (KLN) | 1150 | 1332 | FAIL! | 182
ACACIA ST (KLN) | 1151 | 1332 | FAIL! | 181
ACACIA ST (KLN) | 1606 | 2079 |  | 473
ACTIVITY ST (WRK) | 6 | 215 | WIN! | 209
ACTIVITY ST (WRK) | 215 | 227 | WIN! | 12
ACTIVITY ST (WRK) | 227 | 423 | WIN! | 196
ACTIVITY ST (WRK) | 423 | 549 | WIN! | 126
ACTIVITY ST (WRK) | 549 | 600 |  | 51
ADRIENNE CT (WMN) | 5 | 107 | WIN! | 102
ADRIENNE CT (WMN) | 107 | 122 |  | 15
AERODROME RD (LYB) | 0 | 140 | WIN! | 140
AERODROME RD (LYB) | 140 | 428 | WIN! | 288
AERODROME RD (LYB) | 428 | 716 | WIN! | 288
AERODROME RD (LYB) | 716 | 998 | WIN! | 282
AERODROME RD (LYB) | 998 | 1280 | WIN! | 282
AERODROME RD (LYB) | 1280 | 1566 | WIN! | 286
AERODROME RD (LYB) | 1566 | 1851 | WIN! | 285
AERODROME RD (LYB) | 1851 | 2136 | WIN! | 285
AERODROME RD (LYB) | 2136 | 2421 |  | 285

那么有更多的数据,大约11000 +行。

现在的想法是每个路段(第一列)都有一个起始和结束链(第二和第三列)和一个长度(最后一列),结束链应该是下一个段的起始链,提供路段名称相同(当然按开始链式排序)。你可以看到,因为第一行结束链不等于下一个的开始失败。

我对伪代码的不良尝试:

If EndChainage != NextStartChainge Where RoadSegment = NextRoadSegment Error

我需要做的是选择不遵循末端链规则的所有路段=下一个的开始链接。

所以上表的结果是:

ACACIA ST (KLN) | 1073 | 1149 | FAIL! | 76
ACACIA ST (KLN) | 1073 | 1151 | FAIL! | 78
ACACIA ST (KLN) | 1150 | 1332 | FAIL! | 182
ACACIA ST (KLN) | 1151 | 1332 | FAIL! | 181

希望这是有道理的。我尝试了它,但似乎可以让它工作,我的SQL技能有点缺乏。

编辑:我可以同时使用SQL Server和PostgreSQL。

2 个答案:

答案 0 :(得分:2)

我的第一次尝试很简单但是如果你的ACACIA ST情况正确,当正确的段不是正确的顺序时,它就不能正常运行。

    select * from stackchallenge se
    where not exists (select * from stackchallenge 
where startchain = se.endchain and segment = se.segment)
    and exists (select * from stackchallenge 
where segment = se.segment and endchain > se.endchain)

第二项工作使用了一些SQL 2005特定的语法,但我认为你得到了正确的答案。

     with segments (segment,startchain,endchain,lenchain,segnum)
        as (select segment,startchain,endchain,lenchain
    ,row_number() over (partition by segment order by startchain,endchain) segnum
                from stackchallenge)
        select s1.segment,s1.startchain,s1.endchain,s1.lenchain
            ,case when s1.endchain = s2.startchain then 'WIN!'
                when s1.endchain <> s2.startchain then 'FAIL!'
            else '' end result
        from segments s1
            left join segments s2 on s1.segment = s2.segment 
and s1.segnum + 1 = s2.segnum

以下是用于测试您需要SQL Server 2008直接使用的表和数据。如果您正在使用它,请更改Insert to SQL 2005语法。

create table stackchallenge (segment varchar(100),
    startchain int,
    endchain int,
    result varchar(100),
    lenchain int
)   

insert into stackchallenge (segment,startchain,endchain,result,lenchain)
values 
('ACACIA ST (KLN)' , 1073 , 1149 , 'FAIL!' , 76),
('ACACIA ST (KLN)' , 1073 , 1151 , 'FAIL!' , 78),
('ACACIA ST (KLN)' , 1150 , 1332 , 'FAIL!' , 182),
('ACACIA ST (KLN)' , 1151 , 1332 , 'FAIL!' , 181),
('ACACIA ST (KLN)' , 1606 , 2079 , '' , 473),
('ACTIVITY ST (WRK)' , 6 , 215 , 'WIN!' , 209),
('ACTIVITY ST (WRK)' , 215 , 227 , 'WIN!' , 12),
('ACTIVITY ST (WRK)' , 227 , 423 , 'WIN!' , 196),
('ACTIVITY ST (WRK)' , 423 , 549 , 'WIN!' , 126),
('ACTIVITY ST (WRK)' , 549 , 600 , '' , 51),
('ADRIENNE CT (WMN)' , 5 , 107 , 'WIN!' , 102),
('ADRIENNE CT (WMN)' , 107 , 122 , '' , 15),
('AERODROME RD (LYB)' , 0 , 140 , 'WIN!' , 140),
('AERODROME RD (LYB)' , 140 , 428 , 'WIN!' , 288),
('AERODROME RD (LYB)' , 428 , 716 , 'WIN!' , 288),
('AERODROME RD (LYB)' , 716 , 998 , 'WIN!' , 282),
('AERODROME RD (LYB)' , 998 , 1280 , 'WIN!' , 282),
('AERODROME RD (LYB)' , 1280 , 1566 , 'WIN!' , 286),
('AERODROME RD (LYB)' , 1566 , 1851 , 'WIN!' , 285),
('AERODROME RD (LYB)' , 1851 , 2136 , 'WIN!' , 285),
('AERODROME RD (LYB)' , 2136 , 2421 , '' , 285)

答案 1 :(得分:2)

假设不会有重复的行,以下内容应该是一个与数据库无关的合理解决方案:

select street, startno, endno, 
case  (select coalesce(min(s2.startno),-1) from stackchallenge s2 
       where s1.street = s2.street and 
             s1.startno <= s2.startno and 
             s1.endno < s2.endno)
    when -1 then ' '
    when endno then 'WIN!'
    else 'FAIL!'
end as validated,
length
from stackchallenge s1 order by 1,2,3