SQL选择具有连续相似值的行

时间:2013-02-10 05:55:37

标签: sql sql-server

我有一个名为“Students”的表格,其中包含......

等字段
Student          Code1      Code2      Code3      Code4

Mark             0           1         1          1        1
Joseph           0           1         0          1        0
Bryan.           0           0         1          1        1

因此,SQL查询应该选择具有大于或等于2的1的学生,并且它们也应该是连续的... 在上述情况下..应该返回Mark和Bryan而不是Joseph

2 个答案:

答案 0 :(得分:0)

如果只有少数几列:

Select *
From Students
Where ( Code1 + Code2 ) = 2
    Or ( Code2 + Code3 ) = 2
    Or ( Code3 + Code4 ) = 2
    Or ( Code4 + Code5 ) = 2

另一种解决方案:

With NormalizedData As
    (
    Select Student, Code1, 1 As Sequence From Students Where Code1 = 1
    Union All Select Student, Code2, 2 From Students Where Code2 = 1
    Union All Select Student, Code3, 3 From Students Where Code3 = 1
    Union All Select Student, Code4, 4 From Students Where Code4 = 1
    Union All Select Student, Code5, 5 From Students Where Code5 = 1
    )
Select ...
From Students As S
Where Exists    (
                Select 1
                From NormalizedData As N1
                    Join NormalizedData As N2
                        On N2.Student = N1.Student
                            And N2.Sequence = N1.Sequence + 1
                Where N1.Student = S.Student
                )

答案 1 :(得分:0)

虽然你的架构是非常非常奇怪的,但你可以使用UNPIVOT来解决它,假设你使用的是SQL Server 2005或更高版本。请注意,您必须向unpivot提供所有代码的硬编码列表...

WITH pvt (student, code, value) as (
        SELECT 
            Student,
            ROW_NUMBER()OVER(Partition By Student Order By Codes) as CodeId, 
            Value
        FROM 
            ( select * from students ) P
        UNPIVOT ( 
            Value FOR Codes IN (Code1, Code2, Code3, Code4, Code5) 
        ) Code
    )

    select 
    distinct
        pvt.student
    from 
        pvt
        inner join pvt p2
            on p2.code = pvt.code + 1
            and p2.student = pvt.student
    where 
        pvt.value = 1 and p2.value = 1

这里真正的优点是你只需要在一个地方处理你的各种代码 - 例如,如果你添加Code6,你只需将它添加到UNPIVOT中,它就会被合并到代码中。

另请注意,这只是解决了“学生必须在代码中连续2个1”的更一般要求。它不会检查学生有多少1,或者关心2值下降的位置。

最后一点需要注意的是,ROW_NUMBER()函数假设您的代码按顺序命名,没有间隙,因此如果从Code7转到Code9,它只会假设这两个代码是“连续的”。