问题描述
我正在尝试在Kotlin Exposed中编写一个查询,该查询将多个表连接在一起。一些表可以具有空值,在这种情况下,select
语句应该忽略这些值。
在一个示例中:我有一个UserTable
,一个GeoLocationTable
和一个PhotoTable
。用户将始终具有一个引用的GeoLocation
表,但是该表可能包含照片,也可能没有照片。 UserTable
对PhotoTable
一无所知,但是PhotoTable
有一个userId
作为FK。
我想实现这一点,当我查询用户时-我总是在结果集中收到一个用户。仅当存在带有userId
作为外键的照片时,这些照片才应位于结果集中,否则结果集应仅包含用户。
我的问题是,如果用户的照片不在数据库中,那么我的查询甚至不会返回用户!我在做什么错了?
这是查询。
private fun fetchUserWithPhotos(userId: String) = tx {
val query = UserProfileTable
.join(
joinType = JoinType.LEFT,otherTable = GeoLocationTable,otherColumn = GeoLocationTable.id,onColumn = UserProfileTable.geoLocationId
)
.join(
joinType = JoinType.LEFT,otherTable = PhotoTable,otherColumn = PhotoTable.userId,onColumn = UserProfileTable.id
)
val x = query
.select {
(UserProfileTable.id eq userId) and
(UserProfileTable.deletedAt.isNull()) and
(UserProfileTable.enabled eq true) and
(PhotoTable.userPhotoType eq UserPhotoType.PROFILE.toString()) and
(PhotoTable.position eq 1)
}
// x is empty set here,even though the user EXISTS!
}
解决方法
我想我很直接,我可以从您的代码中解析出的查询可以解决这个问题:
select * from user_profile
left join geo_location on user_profile.geo_location_id = geo_location.id
left join photo on user_profile.id = photo.user_id
where user_profile.id = ?
and user_profile.deleted_at is null
and user_profile.enabled is true
and photo.user_photo_type = 'PROFILE'
and photo.position = 1;
您描述的问题是:'如果该用户的照片不在数据库中,那么我的查询甚至不会返回该用户!我在做什么错?'
问题:您使用的是基于照片表中数据的谓词,您已经声明用户不一定总是有照片条目。如果没有照片,则谓词为假,即使您知道用户存在,也不会选择该行:
and photo.user_photo_type = 'PROFILE'
and photo.position = 1;
建议的解决方案:我认为您可以尝试加入所需的照片并仅在用户表上保留谓词。将查询更新为:
select * from user_profile
left join geo_location on user_profile.geo_location_id = geo_location.id
left join photo on user_profile.id = photo.user_id and photo.position = 1 and photo.user_photo_type = 'PROFILE'
where user_profile.id = ?
and user_profile.deleted_at is null
and user_profile.enabled is true;