SQLite 中一行与另一行的比较

Dan*_* B. 4 sql sqlite android

我有一个安卓应用。在我的 Android 应用程序中,我有一个 SQLite 数据库。在我的 SQLite 数据库中,我有一个如下所示的表:

_id abcd
 1 1 1 1 0
 2 0 1 1 1
 3 1 0 0 1
 4 0 1 0 1

我想计算每一行:在所有列 a、b、c 和 d 中,当前行或前一行中都有 1 的列中,当前行和前一行中都有 1 的百分比是多少?输出将如下所示:

_id abcd 结果
 1 1 1 1 0 空
 2 0 1 1 1 50%
 3 1 0 0 1 25%
 4 0 1 0 1 33%

我可以在 SQLite 之外的 Java 中执行此操作,但我更愿意在 SQL 中执行此操作;这样会更整洁。我应该使用什么查询?

Tho*_*mas 5

Select  CurAndNext.T1_id
    , Sum( Case When D1.Val + D2.Val = 1 Then 1 End ) As CntInEitherRow
    , Sum( Case When D1.Val + D2.Val = 2 Then 1 End ) / 4.000 As PercBoth
From    (
        Select T1._id As T1_id, Max( T2._id ) As T2_id
        From MyTable As T1
            Left Join MyTable As T2
                On T2._id < T1._id
        Group By T1._id
        ) As CurAndNext
    Join    (
            Select _id, 'a' As Col, a As Val From MyTable As T1
            Union All
            Select _id, 'b', b From MyTable As T1
            Union All
            Select _id, 'c', c From MyTable As T1
            Union All
            Select _id, 'd', d From MyTable As T1
            ) As D1
        On D1._id = CurAndNext.T1_id
    Left Join   (
                Select _id, 'a' As Col, a As Val From MyTable As T1
                Union All
                Select _id, 'b', b From MyTable As T1
                Union All
                Select _id, 'c', c From MyTable As T1
                Union All
                Select _id, 'd', d From MyTable As T1
                ) As D2
            On D2._id = CurAndNext.T2_id
                And D2.Col = D1.Col
Group By CurAndNext.T1_Id
Run Code Online (Sandbox Code Playgroud)

使此查询变得困难的一个重要因素是数据是非规范化的。因此,我必须对其进行标准化才能获得您所寻求的信息。


知道什么栏目abcd代表品牌在世界上所有的差异。上述查询的复杂性表明模式不能很好地映射到业务需求。知道它们代表学生出勤率,我们可以设计一个替代方案。

Create Table Student
    (
    Id int not null Primary Key
    , Name varchar(50) not null
    )

Create Table Class
    (
    Id int not null Primary Key
    , Name varchar(50) not null
    )

-- if using dates, this would be the equivalent
-- of a calendar table
Create Table ClassDay 
    ( 
    DayNum int not null Primary Key 
    )

-- ClassDayNum would be better as a Date    
Create Table Attendence
    (
    StudentId int References Student( Id )
    , ClassId int References Class( Id )
    , ClassDayNum int not null  References ClassDay( DayNum )
    , Unique( StudentId, ClassId, ClassDayNum )
    )

Insert Student( Id, Name )
Select 1, 'a'
Union All Select 2, 'b'
Union All Select 3, 'c'
Union All Select 4, 'd'

Insert Class( Id, Name )
Values (1, 'Some Class' )

Insert ClassDay( DayNum )
Select 1
Union All Select 2
Union All Select 3
Union All Select 4

Insert Attendence( ClassId, StudentId, ClassDay )
Select 1, 1, 1
Union All Select 1, 1, 3
Union All Select 1, 2, 1
Union All Select 1, 2, 2
Union All Select 1, 2, 4
Union All Select 1, 3, 1
Union All Select 1, 3, 2
Union All Select 1, 4, 2
Union All Select 1, 4, 3
Union All Select 1, 4, 4
Run Code Online (Sandbox Code Playgroud)

在当前行或前一行中具有 1 的所有 a、b、c 和 d 列中

您的结果读取方式实际上是请求参加某一天而不是前一天或前一天而不是当前的人数。

Select Class.Id, ClassDay.DayNum
    , Count(Distinct A.StudentId) As Attendence
    , Count(Distinct A.StudentId) / 4.000 As Ratio
From Class
    Cross Join Student
    Cross Join ClassDay
    Left Join Attendence As A
        On A.ClassId = Class.Id
            And A.StudentId = Student.Id
            And A.ClassDayNum = ClassDay.DayNum
            And A.ClassDayNum > 1
    Left Join Attendence As A2
        On A2.ClassId = Class.Id
            And A2.StudentId = Student.Id
            And A2.ClassDayNum = ClassDay.DayNum - 1
Where Not( A.StudentId Is Not Null And A2.StudentId Is Not Null )
Group By Class.Id, ClassDay.DayNum
Run Code Online (Sandbox Code Playgroud)

结果:

DayNum 出席人数 | 比率
1 | 0 | 0
2 | 1 | .25
3 | 1 | .25
4 | 1 | .25

当前行和上一行中都有 1 的百分比是多少

Select ClassDay.DayNum
    , Sum( Case When A.StudentId Is Not Null And A2.StudentId Is Not Null Then 1 End )
    , Sum( Case When A.StudentId Is Not Null And A2.StudentId Is Not Null Then 1 End ) / 4.000
From Class
    Cross Join Student
    Cross Join ClassDay
    Left Join Attendence As A
        On A.ClassId = Class.Id
            And A.StudentId = Student.Id
            And A.ClassDayNum = ClassDay.DayNum
            And A.ClassDayNum > 1
    Left Join Attendence As A2
        On A2.ClassId = Class.Id
            And A2.StudentId = Student.Id
            And A2.ClassDayNum = ClassDay.DayNum - 1
Group By ClassDay.DayNum            
Run Code Online (Sandbox Code Playgroud)
日数 | 出席 | 比率
1 | 空 | 空值
2 | 2 | 0.500000
3 | 1 | 0.250000
4 | 1 | 0.250000

  • 如果这被接受作为答案,我将辞去 Java 开发人员的工作,搬到阿拉斯加开采黄金。 (4认同)