不考虑 JOIN 类型,使用 :-
SELECT entries.*, myProfile.myProfileId as my_profile_id FROM Entry as entries LEFT JOIN MyProfile ON entries.user_public_profile_userId = myProfile.myProfileId
将导致 my_profile_id 与存储在 user_public_profile_userId 列中的值相同。从这个意义上说,JOIN 是浪费时间。
我怀疑您可能想从 MyProfile 表中获取另一个有用的值。
假设您有一个 Entry 实体,它类似于:-
@Entity
data class Entry(
@PrimaryKey
val id: Long? = 0,
val name: String,
@ColumnInfo(name = "my_profile_id")
val myUserProfileId: Long? = null,
val user_public_profile_userId: Long
)
还有一个 MyProfile 实体,类似于:-
@Entity
data class MyProfile(
@PrimaryKey
val myProfileId: Long? = null,
val otherdata: String
)
如果您想从 otherdata 列中获取值,那么您需要一个额外的 POJO 来组合数据。
因此考虑这样的 POJO EntryPlus :-
data class EntryPlus(
@Embedded
val entry: Entry,
val profileIdFromMyProfile: Long,
val otherdataFromMyProfile: String
)
- @Embedded 和下面一行是说你想要条目表中的所有列/字段
- 其他两列将来自其他地方(满足查询)
所以你可以有一个查询,例如:-
@Query("SELECT entries.*, myProfile.myProfileId AS profileIdFromMyProfile, myProfile.otherdata AS otherdataFromMyProfile FROM Entry as entries LEFT JOIN MyProfile ON entries.user_public_profile_userId = myProfile.myProfileId")
fun getMyOtherData(): List<EntryPlus>
- 即查询略有不同,但重要的是使用
AS 来相应地命名输出列以适合 EntryPlus POJO 中的字段名称。
- 同样重要的是,结果是 POJO (EntryPlus) 的列表。
示例
考虑以下代码:
- 插入一些数据(3 个 MyProfile 行和 2 个 Entry 行),然后
- 使用
SELECT * FROM entry 提取所有没有 JOIN 的 Entry 行,然后
- 使用您的原始查询进行提取,然后
- 通过 POJO 提取
代码是:-
db = TheDatabase.getInstance(this) // Get database instance
dao = db.getAllDao() // get the Dao
dao.deleteAllMyProfile() // Clear the MyProfile table
dao.deleteAllEntry() // Clear the Entry table
// Add some profile rows
dao.insert(MyProfile(1,"myprofile1"))
dao.insert(MyProfile(2,"myprofile2"))
dao.insert(MyProfile(3,"myprofile3"))
// Add some Entry rows (both link to profile1 in this case)
dao.insert(Entry(100,"Entry1",0,1))
dao.insert(Entry(200,"Entry2",0,1))
// Extract 1 All as Entry List (no join)
for(e: Entry in dao.getAll()) {
Log.d("ENTRYINFO(1)","Entry Name is ${e.name} EntryID is ${e.id} MapToMyProfile is ${e.user_public_profile_userId} Value is ${e.myUserProfileId}" )
}
// Extract 2 All from original query
for(e: Entry in dao.getMyData()) {
Log.d("ENTRYINFO(2)","Entry Name is ${e.name} EntryID is ${e.id} MapToMyProfile is ${e.user_public_profile_userId} Value is ${e.myUserProfileId}" )
}
// Extract 3 getting useful data from the 2nd (JOINED) table
for(ep: EntryPlus in dao.getMyOtherData()) {
Log.d("ENTRYINFO(3)",
"Entry Name is ${ep.entry.name} EntryID is ${ep.entry.id} MapToMyProfile is ${ep.entry.user_public_profile_userId} Myuserprofile(From Entry) ${ep.entry.myUserProfileId}" +
" MyProfileId (From MyProfile) is ${ep.profileIdFromMyProfile} OtherData (From MyProfile) is ${ep.otherdataFromMyProfile}" )
}
日志的输出是:-
2021-07-07 09:44:12.665 D/ENTRYINFO(1): Entry Name is Entry1 EntryID is 100 MapToMyProfile is 1 Value is 0
2021-07-07 09:44:12.665 D/ENTRYINFO(1): Entry Name is Entry2 EntryID is 200 MapToMyProfile is 1 Value is 0
2021-07-07 09:44:12.666 D/ENTRYINFO(2): Entry Name is Entry1 EntryID is 100 MapToMyProfile is 1 Value is 1
2021-07-07 09:44:12.666 D/ENTRYINFO(2): Entry Name is Entry2 EntryID is 200 MapToMyProfile is 1 Value is 1
2021-07-07 09:44:12.667 D/ENTRYINFO(3): Entry Name is Entry1 EntryID is 100 MapToMyProfile is 1 Myuserprofile(From Entry) 0 MyProfileId (From MyProfile) is 1 OtherData (From MyProfile) is myprofile1
2021-07-07 09:44:12.668 D/ENTRYINFO(3): Entry Name is Entry2 EntryID is 200 MapToMyProfile is 1 Myuserprofile(From Entry) 0 MyProfileId (From MyProfile) is 1 OtherData (From MyProfile) is myprofile1
输出说明
前两行注意 MyProfileId 值(即 Value =)在插入时为 0。
第二两行使用您的原始查询显示 MyProfileId (Value =) 现在与 MyProfile 行的链接/引用/关联/关系(即user_public_profile_userId 列)的值相同。
第三个表示已从 MyProfile 表(otherdata 列)中提取值。
但是,您似乎还描述了 LEFT JOIN 与仅 JOIN 相比的性质。
如果在提取之前添加了以下行(另一个 Entry 行但引用了不存在的 MyProfile 行):-
dao.insert(Entry(300,"Entry3",999,10 /* 10 = No such myprofile row */))
那么结果中的变化将是显着的,因为第二次提取会根据以下内容为 my_profile_id 检索 null:-
D/ENTRYINFO(2): Entry Name is Entry3 EntryID is 300 MapToMyProfile is 10 Value is null
更改为仅 JOIN(而不是 LEFT JOIN)并省略引用不存在的 MyProfile 的行。这是记录在案的影响:-
如果连接运算符是“LEFT JOIN”或“LEFT OUTER JOIN”,则在应用 ON 或 USING 过滤子句后,将在原始左侧的每一行的输出中添加一个额外的行输入数据集对应于复合数据集中的任何行(如果有)。添加的行在通常包含从右侧输入数据集复制的值的列中包含 NULL 值。
在空值的情况下,如果这是您的问题,那么您需要决定要做什么。
-
例如,您可以使用 SQLite COALESCE 函数来更改空值。例如SELECT entries.*, coalesce(myProfile.myProfileId,9999) as my_profile_id FROM Entry ....
-
也许您需要确保保持参照完整性,在这种情况下,您可以利用 FOREIGN KEYS 来强制执行参照完整性。或许可以参考Foreign Key