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 中执行此操作;这样会更整洁。我应该使用什么查询?
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)
使此查询变得困难的一个重要因素是数据是非规范化的。因此,我必须对其进行标准化才能获得您所寻求的信息。
知道什么栏目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
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
| 归档时间: |
|
| 查看次数: |
2025 次 |
| 最近记录: |