如何显示每个/选定月份的总费用?

时间:2019-04-05 12:23:29

标签: android sqlite android-sqlite

我想在日历下方显示每个/选定月份的总费用。

我将费用总额存储在这样的数据库中:

  public double getTotal(String email, int month) {
    SQLiteDatabase db = this.getWritableDatabase();
    int total;

    Cursor cursor = db.rawQuery("SELECT SUM( Amount ) as Amount FROM " + "UserExpenses" +  " WHERE " + KEY_MONTH + "=" + month + "",null);

    if (cursor.moveToFirst()) {

         total = cursor.getInt(cursor.getColumnIndex("Amount"));// get final total
         return total;
    }
    else
        total = -1;
    cursor.close();
    return 0;
}

即使滚动月份,我也只能得到所选月份的总费用

 Calendar c = Calendar.getInstance();
        int month = c.get(Calendar.MONTH);

        totalExpense = dataBaseHelper.getTotal(email, month);

        expense = findViewById(R.id.expense);
        expense.setText(String.valueOf(totalExpense));

1 个答案:

答案 0 :(得分:2)

您可以对使用GROUP BY子句分组的数据运行使用sum(x)函数的查询。

  • 其中x代表列名。

sum(x)基金是一个聚合函数,返回添加x列的结果,该列将作用于GROUP BY子句确定的一组行。

GROUP BY子句应根据年份和月份分组。

因此,SQL将遵循

SELECT  sum(your_amount_column), your_year_column, your_month_column FROM your_table GROUP BY your_email_column,your_year_column, your_month_column;

要根据日历下方每个<选定的月份/选定的月份进行选择。。那么WHERE子句也应允许选择。通过将日期存储为单独的实体(例如,年月日是单独的列),选择起来很复杂。因此要选择一个日期范围(假设存储了jan 1 ,存储了2月2日,等等),那么当20192(2019年2月)大于201912(排序时,如果简单地串联起来),就会出现问题。需要一些操作,例如将年份乘以100再加上。

选择日期范围时,可以使用使用BETWEEN子句的WHERE子句:-

WHERE (year * 100) + month BETWEEN ((start_year * 100) + start_month) AND ((end_year * 100) + end_month)
  • 以上假设适用于所有电子邮件帐户(每个电子邮件帐户都有单独的行/总和)。对于单个电子邮件帐户,将添加WHERE子句。

SQL示例

请考虑以下内容:-

DROP TABLE IF EXISTS user_balance;
CREATE TABLE IF NOT EXISTS  user_balance (email TEXT, amount REAL, description TEXT, year INTEGER, month INTEGER, day INTEGER, created_at TEXT);
INSERT INTO user_balance VALUES
    ('Fred',5.50,'blah',2019,01,01,'2019-01-01 10:30'),
    ('Fred',10.50,'blah',2019,01,02,'2019-01-01 10:30'),
    ('Fred',15.50,'blah',2019,01,13,'2019-01-01 10:30'),
    ('Fred',20.50,'blah',2019,02,04,'2019-01-01 10:30'),
    ('Fred',25.50,'blah',2019,02,05,'2019-01-01 10:30'),

    ('Mary',145.25,'blah',2019,01,01,'2019-01-01 10:30'),
    ('Mary',145.25,'blah',2019,01,02,'2019-01-01 10:30'),
    ('Mary',145.25,'blah',2019,01,13,'2019-01-01 10:30'),
    ('Mary',145.25,'blah',2019,02,04,'2019-01-01 10:30'),
    ('Mary',145.25,'blah',2019,02,05,'2019-01-01 10:30'),

    ('Joan',345.25,'blah',2019,01,01,'2019-01-01 10:30'),
    ('Joan',345.25,'blah',2019,01,02,'2019-01-01 10:30'),
    ('Joan',345.25,'blah',2019,01,13,'2019-01-01 10:30'),
    ('Joan',345.25,'blah',2019,02,04,'2019-01-01 10:30'),
    ('Joan',345.25,'blah',2019,02,05,'2019-01-01 10:30'),

    ('Fred',45.25,'blah',2018,01,01,'2019-01-01 10:30'),
    ('Fred',45.25,'blah',2018,01,02,'2019-01-01 10:30'),
    ('Fred',45.25,'blah',2018,01,13,'2019-01-01 10:30'),
    ('Fred',45.25,'blah',2018,02,04,'2019-01-01 10:30'),
    ('Fred',45.25,'blah',2018,02,05,'2019-01-01 10:30'),

    ('Mary',145.25,'blah',2018,01,01,'2019-01-01 10:30'),
    ('Mary',145.25,'blah',2018,01,02,'2019-01-01 10:30'),
    ('Mary',145.25,'blah',2018,01,13,'2019-01-01 10:30'),
    ('Mary',145.25,'blah',2018,02,04,'2019-01-01 10:30'),
    ('Mary',145.25,'blah',2018,02,05,'2019-01-01 10:30'),

    ('Joan',345.25,'blah',2018,01,01,'2019-01-01 10:30'),
    ('Joan',345.25,'blah',2018,01,02,'2019-01-01 10:30'),
    ('Joan',345.25,'blah',2018,01,13,'2019-01-01 10:30'),
    ('Joan',345.25,'blah',2018,02,04,'2019-01-01 10:30'),
    ('Joan',345.25,'blah',2018,02,05,'2019-01-01 10:30')
;
SELECT email, sum(amount) AS balance, year, month 
    FROM user_balance 
    WHERE 
        ((year * 100) + month) BETWEEN ((2018 * 100) + 09) AND ((2019 * 100) + 09)  
    GROUP BY email,year,month ;
SELECT email, sum(amount) AS balance, year, month 
    FROM user_balance 
    WHERE 
        ((year * 100) + month) BETWEEN ((2018 * 100) + 09) AND ((2019 * 100) + 09)  
        and email = 'Mary' 
    GROUP BY email,year,month;

  1. 此示例拖放并创建user_balance表(为了方便运行/测试/更改)。
  2. 为3个电子邮件/用户添加一些测试数据,每个电子邮件/用户的数据为2个月,为期2年。
  3. 为2018年9月(2018 09)-2019年9月(2019 09)之间的日期选择所有电子邮件/用户每个月的收入(金额)之和。
  4. 如上所述,但针对特定的电子邮件/用户。

两个结果是:-

enter image description here

enter image description here

4个Android(Java)

要与Android一起使用并使用SQLiteDatabase query方法返回游标,则可以使用以下方法:-

public Cursor getUserBalance(String email, int start_year, int start_month, int end_year, int end_month) {
    String[] columns = new String[]{
            KEY_EMAIL,
            "sum(" + KEY_AMOUTNT + ") AS balance",
            KEY_YEAR,
            KEY_MONTH
    };
    String whereclause = "((year * 100) + month) BETWEEN ((? * 100) + ?) AND ((? * 100) + ?)  and email = ?";
    String[] whereargs = new String[]{
            String.valueOf(start_year),
            String.valueOf(start_month),
            String.valueOf(end_year),
            String.valueOf(end_month),
            email
    };
    String groupbyclause = KEY_EMAIL + "," + KEY_YEAR + "," + KEY_MONTH;

    SQLiteDatabase db = this.getWritableDatabase();
    return db.query(TABLE_USER_BALANCE,columns,whereclause,whereargs,groupbyclause,null,null);
}
  • 注意以上为原则代码,尚未经过测试或运行,因此可能包含错误。
  • 考虑以下内容,您可能希望将此方法命名为更具描述性的名称,例如也许getUserBalanceAsCursor(显然,随后将相应地更改以下内容)。

以上内容实际上并未返回特定用户/月的余额,但对于其他情况可能有用。要返回余额(假设是双倍),则以下方法利用先前的方法在特定月份执行此操作:-

public double getUserBalance(String email, int year, int month) {
    double rv = 0.0;
    Cursor csr = getUserBalance(email,year,month,year,month);
    if (csr.moveToFirst()) {
        rv = csr.getDouble(csr.getColumnIndex("balance"));
    }
    csr.close();
    return rv;
}
  • 注意以上为原则代码,尚未经过测试或运行,因此可能包含错误。