Как отобразить общие расходы за каждый выбранный месяц? - PullRequest
0 голосов
/ 05 апреля 2019

Я хочу отобразить общие расходы каждого / выбранного месяца ниже календаря.

Я сохранил итоговую сумму в базе данных следующим образом:

  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 Ответ

2 голосов
/ 05 апреля 2019

Вы можете выполнить запрос, который использует функцию sum (x) для данных, которые были сгруппированы с помощью предложения GROUP BY.

  • , где x представляет имя столбца.

sumtion (x) fundtion - это агрегатная функция, которая возвращает результат добавления столбца 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 сохранено, для feb 2 сохранено и т. Д.), Возникают проблемы, поскольку 20192 (февраль 2019) больше 201912 (сортировка целесообразна, если просто объединяется), поэтому некоторыетребуется манипулирование, например, путем умножения года на 100 и добавления.

Таким образом, для выбора диапазона дат в предложении WHERE с использованием предложения BETWEEN можно использовать что-то вроде: -

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 г. (2018 г. 09) - сентябрь 2019 г. (2019 г. 09).
  4. Как указано выше, но для определенного адреса электронной почты / пользователя.

Два результата: -

enter image description here

и

enter image description here

4 Android (Java)

Для использования с Android и использования базы данных SQLiteDatabase метод для возврата курсора, который вы могли бы затем использовать что-то вроде: -

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);
}
  • NOTE приведенный выше код в принципе, этоне был протестирован или запущен и, следовательно, может содержать ошибки.
  • Учитывая следующее, вы можете назвать этот метод более описательным, например, возможно, 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;
}
  • ПРИМЕЧАНИЕ вышеизложенное является в принципекод, он не был протестирован или запущен и поэтому может содержать ошибки.
...