J'utilise Room sur Android pour interroger un POJO.
Mon POJO (Transaction) contient une valeur
et un account_id
. Il contient en outre un compte
(instance de Account), qui est récupéré par un @Relation
.
La classe de transaction:
@androidx.room.Transaction @Query( """ SELECT transactions.* FROM transactions LEFT OUTER JOIN (SELECT transactions.value, SUM(transactions.value) AS balance FROM accounts) ON transactions.account_id = accounts.id GROUP BY transactions.id """ ) fun getTrs(): List<Transaction>
Les propriétés des comptes:
data class Account( @PrimaryKey(autoGenerate = true) @ColumnInfo(name = Database.Accounts.COL_ID) val id: Long = 0, @ColumnInfo(name = Database.Accounts.COL_NAME) val name: String = "", @ColumnInfo(name = Database.Accounts.COL_BALANCE) val balance: Double = 0.0 )
Le accounts.balance
n'est pas une valeur dans la base de données, mais la somme de toutes les transactions.value
appartenant à ce compte.
Je dois donc additionner chaque transaction.value
où transaction.account_id = account. id
.
Cela devrait fonctionner de la même manière, mais je ne fais pas les choses correctement:
@Parcelize class Transaction( @Embedded val entity: TransactionEntity, @Relation(entity = Account::class, parentColumn = Database.Transactions.COL_ACCOUNT_ID, entityColumn = Database.Accounts.COL_ID) val account: Account? = null ) : Model
6 Réponses :
essayez ceci:
@androidx.room.Transaction @Query( """ SELECT transactions.* FROM transactions LEFT OUTER JOIN (SELECT transactions.value, SUM(transactions.value) AS balance FROM accounts GROUP BY transactions.id) ON transactions.account_id = accounts.id """ ) fun getTrs(): List<Transaction>
Vous avez listé toutes les colonnes nécessaires de vos transactions de table dans la clause GROUP BY.
SELECT transactions.* SUM(transactions.value) AS balance FROM transactions LEFT JOIN accounts ON transactions.account_id = accounts.id GROUP BY ...transactions.id, transactions.account_id.... and all necessary columns of transactions table...
J'espère vous avoir aidé!
Vous pouvez utiliser la sous-requête:
SELECT t.*,(SELECT SUM(transactions.value) FROM accounts a ON t.account_id = a.id) AS balance FROM transactions t
Rendez-le propre: Créez d'abord une vue de solde
SELECT account.*, IFNULL(v_balance.account_balance, 0.0) FROM account LEFT JOIN v_balance ON v_balance.account_id = account.id
Ensuite, utilisez la vue dans la jointure gauche comme vous le souhaitez:
CREATE VIEW v_balance AS SELECT account_id, SUM(value) as account_balance FROM transactions GROUP BY account_id
Cela a probablement la même signification:
SELECT a.*, SUM(t.value) AS balance FROM transactions t LEFT JOIN accounts a ON a.account_id = t.account_id GROUP BY t.account_id
Je l'ai fait en créant un nouveau POJO encapsulant mon objet de compte d'origine, mais en ajoutant un champ pour la somme qui est maintenant interrogée.
@Query( """ SELECT accounts.*, (SELECT SUM(CASE WHEN transactions.type = ${Transaction.TransactionType.EARNING} THEN transactions.value ELSE -transactions.value END) FROM transactions WHERE transactions.account_id = accounts.id) AS balance FROM accounts LEFT JOIN transactions ON transactions.account_id = accounts.id GROUP BY accounts.id """ ) fun getAccountsWithBalance(): LiveData<List<AccountWithBalance>>
Quelle est la raison de
LEFT JOIN
(par opposition àINNER JOIN
)?en supposant que vous vouliez le solde d'un compte connu, pourquoi ne pas simplement sélectionner la somme (t.value) des transactions t où t.id = 'myknownaccounid' ?
si vous voulez quelque chose de global.
sélectionnez t.id, sum (t.value) dans le groupe de transactions par t.id;
je n'ai pas besoin d'un joint.
@Tuckbros Désolé pour la réponse tardive, je veux un objet Compte avec la somme / solde de ses transactions associées. C'est pourquoi je pense qu'un JOIN est nécessaire.
Je ne sais rien de POJO donc je ne peux pas vous aider à construire un objet. mais si vous souhaitez récupérer le solde d'un compte donné (l'ID de compte est connu avant de créer l'objet, cette valeur de solde unique peut être récupérée avec la première requête. Si vous souhaitez collecter plus que le solde à la fois, c'est-à-dire les données de la table de compte alors vous devrez les obtenir, les rejoindre ou quoi que ce soit d'autre.