我有一个Android应用。在我的Android应用程序中,我有一个SQLite数据库。在我的SQLite数据库中,我有一个如下所示的表:
_id a b c d 1 1 1 1 0 2 0 1 1 1 3 1 0 0 1 4 0 1 0 1
我想计算每一行:在当前或上一行中有一个1的所有列a,b,c和d,当前和上一行中有一个1的百分比是多少?输出看起来像这样:
_id a b c d result 1 1 1 1 0 NULL 2 0 1 1 1 50% 3 1 0 0 1 25% 4 0 1 0 1 33%
我可以在SQLite之外的Java中执行此操作,但我宁愿在SQL中执行此操作;它会更整洁。我应该使用什么查询?
答案 0 :(得分:4)
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
使查询困难的一个重要因素是数据被非规范化。因此,我必须将其标准化才能获得您所寻求的信息。
了解哪些列a
,b
,c
和d
代表了世界上的所有差异。上述查询的复杂性表明模式不能很好地映射到业务需求。知道他们代表学生出勤,我们可以设计一个替代模式。
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
所有a,b,c和d列中当前或前一行都有1的
您的结果实际读取的方式是请求一天而不是之前的或前一天而不是当前的人数。< / p>
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
结果:
DayNum Attendence | Ratio 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
DayNum | Attendence | Ratio 1 | NULL | NULL 2 | 2 | 0.500000 3 | 1 | 0.250000 4 | 1 | 0.250000