Diesel:添加子查询的结果

Diesel: Adding result of subqueries

给定下表:

accounts (
  id INTEGER,
  opening_balance INTEGER,
)

transactions (
  debit INTEGER,
  credit INTEGER,
  amount INTEGER

  foreign key debit references accounts (id),
  foreign key credit references accounts (id)
)

我想执行以下 SQL 查询:

select
  id,
  opening_balance
  + (select sum(amount) from transactions where debit = account_id)
  - (select sum(amount) from transactions where credit = account_id)
from accounts;

我试过这样的事情:

accounts
    .select((
        id,
        opening_balance
            + transactions::table
                .select(sum(transactions::amount))
                .filter(transactions::debit.eq(id))
            - transactions::table
                .select(sum(transactions::amount))
                .filter(transactions::credit.eq(id)),
    ))

虽然此查询的各个部分工作正常,但我无法对其进行编译。

the trait bound 
`diesel::query_builder::SelectStatement<schema::transactions::table, diesel::query_builder::select_clause::SelectClause<aggregate_folding::sum::sum<diesel::sql_types::Integer, schema::transactions::columns::amount>>, diesel::query_builder::distinct_clause::NoDistinctClause, diesel::query_builder::where_clause::WhereClause<diesel::expression::operators::Eq<schema::transactions::columns::debit, schema::fiscal_year_accounts::columns::account_id>>>: diesel::Expression`
is not satisfied
required because of the requirements on the impl of `AsExpression<diesel::sql_types::Integer>` for 
`diesel::query_builder::SelectStatement<schema::transactions::table, diesel::query_builder::select_clause::SelectClause<aggregate_folding::sum::sum<diesel::sql_types::Integer, schema::transactions::columns::amount>>, diesel::query_builder::distinct_clause::NoDistinctClause, diesel::query_builder::where_clause::WhereClause<diesel::expression::operators::Eq<schema::transactions::columns::debit, schema::fiscal_year_accounts::columns::account_id>>>`

+- 运算符使用静态值,但如何让它们使用子查询?

首先:始终提供一个完整的最小示例来说明您的问题。这包括所有已用包的确切版本、使您的代码实际产生此错误消息的所有相关导入、包含所有帮助和通知语句的完整错误消息以及在柴油机情况下生成的模式文件。

回答你的问题:你错过了两次调用 .single_value() ,这是将查询转换为可用作表达式的子查询所必需的。两个子查询 return a Nullable<BigInt> 因此需要 opening_balance 作为匹配类型。

为了完整起见,请参阅下面的工作代码

#[macro_use]
extern crate diesel;
use diesel::prelude::*;

table! {
    accounts {
        id -> Integer,
        // changed to `BigInt` as a sum of `Integer` returns a `BigInt`
        opening_balance -> BigInt,
    }
}

table! {
    transactions {
        id -> Integer,
        amount -> Integer,
        debit -> Integer,
        credit -> Integer,
    }
}

allow_tables_to_appear_in_same_query!(accounts, transactions);

fn test() {
    use self::accounts::dsl::*;
    use diesel::dsl::sum;

    let _q = accounts.select((
        id,
        opening_balance.nullable() // call `.nullable()` here to explicitly mark it as potential nullable
            + transactions::table
                .select(sum(transactions::amount))
                .filter(transactions::debit.eq(id))
                .single_value() // call `.single_value()` here to transform this query into a subquery
            - transactions::table
                .select(sum(transactions::amount))
                .filter(transactions::credit.eq(id))
                .single_value(), // call `.single_value()` here to transform this query into a subquery
    ));
}