如何解决Android 房间一对多并计算值
我在房间里有一对多的关系。 我需要获取数据列表并计算每个对象的一个属性作为金额的总和。 我可以为此写一个查询吗?或者我必须遍历代码中的值?
更新
@Entity(tableName = "account_table")
class AccountModel(
@PrimaryKey(autoGenerate = true)
val id: Int = 0,var name: String,var bankNumber: String,var amount: Double
)
@Entity(tableName = "spent_table")
data class SpentModel(
var amount: Double,var title: String,var description: String,var date: String?,var accountId: Int,@PrimaryKey(autoGenerate = true)
val id: Int = 0,)
data class AccountWithSpent(
@Embedded val account: AccountModel,@Relation(
parentColumn = "id",entityColumn = "accountId"
)
val spent: List<SpentModel>
)
AccountWithSpent
是我的数据的一对多关系,我想从花费中获取所有金额并将其存储到帐户对象金额属性中。
解决方法
我可以为此写一个查询吗?
是
还是我必须遍历代码中的值?
不,但你可以。
注意尽管内容可能有用,但您可能希望直接到底部阅读附加/更正部分。
假设您想在检索一个或多个 AccountWithSpent 对象时获得花费的总和,那么您可以在 AccountWithSpent 中为此包含一个 val/字段,例如:-
data class AccountWithSpent(
@Embedded val account: AccountModel,@Relation(
parentColumn = "id",entityColumn = "accountId"
)
val spent: List<SpentModel>,val sumOfSpent: Double /*<<<<< ADDED for SUM*/
)
然后你可以有一个查询,例如:-
@Transaction
@Query("SELECT *,(SELECT sum(spent_table.amount) FROM spent_table WHERE spent_table.accountId = a.id) AS sumOfSpent FROM account_table AS a")
fun getAccountWithSpent(): List<AccountWithSpent>
-
AS sumOfSpent
很重要,它将要从中获取数据的列命名为与 POJO 中的字段相同的名称,它们必须匹配。 -
AS a
消除 id 列在子查询 ((SELECT sum(spent_table.amount) FROM spent_table WHERE spent_table.accountId = a.id)
) 的 WHERE 子句中使用时的歧义- 即account_table 和paid_table 都有一个id 列。因此,使用 a.id 强制使用 account_table id。
您也可以有一个查询,例如:-
@Transaction
@Query("SELECT account_table.*,sum(spent_table.amount) AS sumOfSpent FROM account_table JOIN spent_table ON account_table.id = spent_table.accountId GROUP BY account_table.id")
fun getAccountWithSpentV2(): List<AccountWithSpent>
- 这不使用子查询,而是使用 JOIN 的表并使用 GROUP BY 将行分组到帐户中。
- 为了抑制 Room 发出警告的未使用列(来自已用表),
account_table.*
用于定义输出列(即仅来自帐户表的列)- Room 再次从帐户构建底层 Spent 对象
替代方案
如果您只想要带有 Sum 的 Account 而不是底层 Spent 对象的 List,那么您可以使用以下内容:-
data class AccountWithSumOfSpent(
@Embedded
val account: AccountModel,val sumOfSpent: Double
)
与:-
@Query("SELECT *,sum(spent_table.amount) AS sumOfSpent FROM account_table JOIN spent_table ON account_table.id = spent_table.accountId GROUP BY account_table.id")
fun getAccountWithSumofSpent(): List<AccountWithSumOfSpent>
-
注意
@Transaction
不是必需的,因为所有数据都是通过单个查询提取的- 子查询嵌入在主查询中。但是,当使用 @Relation Room 时,除了主查询之外,还会构建和执行查询,因此它会警告使用
@Transaction
- 子查询嵌入在主查询中。但是,当使用 @Relation Room 时,除了主查询之外,还会构建和执行查询,因此它会警告使用
使用两种方法的工作示例
/* ADD 1 Account with 3 Spends (totalling $100.00) */
val account1Id = dao.insert(AccountModel(0,"BANKX","000000",0.00)).toInt()
dao.insert(SpentModel(30.00,"SPEND1","BUYA","2021-06-25",account1Id))
dao.insert(SpentModel(30.00,"SPEND2","BUYB","2021-06-24",account1Id))
dao.insert(SpentModel(40.00,"SPEND3","BUYC","2021-06-23",account1Id))
/* Extract and Log using first method (Account,with Sum and with all Spends) */
for(a: AccountWithSpent in dao.getAccountWithSpent()) {
Log.d("ACCNTINFO","Account Name is ${a.account.name} Bank Number is ${a.account.bankNumber} SUM of Spend is ${a.sumOfSpent}")
//Log.d("ACCNTINFO","Account Name is ${a.account.name} Bank Number is ${a.account.bankNumber}")
for(s: SpentModel in a.spent) {
Log.d("ACCNTINFO","Title is \t${s.title} Description is ${s.description} Date is ${s.date} Amount is ${s.amount}")
}
}
/* Extract and Log using second method (no Spends) */
for(a: AccountWithSumOfSpent in dao.getAccountWithSumofSpent()) {
Log.d("ACCNTINFO","Account Name is ${a.account.name} Bank Number is ${a.account.bankNumber} SUM of Spend is ${a.sumOfSpent}")
}
结果
日志包括:-
2021-06-26 07:58:55.265 D/ACCNTINFO: Account Name is BANKX Bank Number is 000000 SUM of Spend is 100.0
2021-06-26 07:58:55.265 D/ACCNTINFO: Title is SPEND1 Description is BUYA Date is 2021-06-25 Amount is 30.0
2021-06-26 07:58:55.265 D/ACCNTINFO: Title is SPEND2 Description is BUYB Date is 2021-06-24 Amount is 30.0
2021-06-26 07:58:55.265 D/ACCNTINFO: Title is SPEND3 Description is BUYC Date is 2021-06-23 Amount is 40.0
2021-06-26 07:58:55.268 D/ACCNTINFO: Account Name is BANKX Bank Number is 000000 SUM of Spend is 100.0
补充/更正
我需要获取数据列表并计算每个对象的一个属性作为数量总和。 AccountWithSpent 是我的数据的一对多关系,我想从支出中获取所有金额并将其存储到帐户对象金额属性中。
我没有正确阅读以上内容,因此根据您的原始 AccountWithSpent,您可以使用:-
@Transaction
@Query("SELECT account_table.id,account_table.name,account_table.bankNumber,sum(spent_table.amount) AS amount FROM account_table JOIN spent_table ON account_table.id = spent_table.accountId GROUP BY account_table.id")
fun getAccountWithSpent(): List<AccountWithSpent>
并且 AccountModel 的金额将相应地填充。
但是,需要注意的是,数据库中的数量仍然是原来的,不会改变。一个反问句,你需要在数据库中保存多少,因为它总是可以计算的?
也许 AccountModel 有:-
.....
@Ignore
var amount: Double
如果您想要数据库中的数量,那么也许您应该始终维护数据库中的数量。如果是这样,那么您可能希望在添加/删除或更新支出时考虑使用 TRIGGER(s) 以自动调整金额(如果是这样,那将是另一个问题)。 >
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。