1
votes

Valeur de l'entité Sqlite SUM en fonction de la valeur LEFT JOIN

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 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 commentaires

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.


6 Réponses :


0
votes

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> 


0 commentaires

0
votes

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é!


0 commentaires

0
votes

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


0 commentaires

0
votes

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


0 commentaires

0
votes

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


0 commentaires

0
votes

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>>


0 commentaires