简体   繁体   English

Android:按月计算总和和分组(SQLite)

[英]Android : Calculate sum and group by month (SQLite)

Is there are any option to select amount, group them by month and calculate sum. 是否可以选择金额,按月分组并计算总和? I tried to get total sum of each month and pass it to ArrayList. 我试图获取每个月的总和并将其传递给ArrayList。
Example of data: 数据示例:

Amount    Date
230       04/03/19
500       05/03/19
400       04/04/19
600       06/04/19
100       04/03/19
...       ...

My code structure 我的代码结构

private String CREATE_BILLS_TABLE = "CREATE TABLE " + TABLE_BILLS + "("
            + COLUMN_BILL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
            + COLUMN_BILL_USER_ID + " INTEGER,"
            + COLUMN_DESCRIPTION + " TEXT,"
            + COLUMN_AMOUNT + " INTEGER,"
            + COLUMN_DATE_STRING + " TEXT,"
            + COLUMN_COMPANY_NAME + " TEXT,"
            + COLUMN_CATEGORY + " TEXT,"
            + " FOREIGN KEY ("+COLUMN_BILL_USER_ID+") REFERENCES "+TABLE_USER+"("+COLUMN_USER_ID+"));";

 public ArrayList<Bills> getDateByUserID(int userID){
        SQLiteDatabase db = this.getReadableDatabase();
        // sorting orders
        ArrayList<Bills> listBillsDates = new ArrayList<Bills>();

        Cursor cursor = db.query(TABLE_BILLS, new String[] { COLUMN_BILL_ID,
                        COLUMN_BILL_USER_ID, COLUMN_DESCRIPTION, COLUMN_AMOUNT, COLUMN_DATE_STRING, COLUMN_COMPANY_NAME, COLUMN_CATEGORY}, COLUMN_BILL_USER_ID + "=?",
                new String[] { String.valueOf(userID) }, COLUMN_DATE_STRING, null, null, null);
        if (cursor.moveToFirst()) {
            do {
                Bills bills = new Bills();
                bills.setAmount(cursor.getInt(cursor.getColumnIndex(COLUMN_AMOUNT)));
                bills.setDateString(cursor.getString(cursor.getColumnIndex(COLUMN_DATE_STRING)));
                // Adding record to list
                listBillsDates.add(bills);
            } while (cursor.moveToNext());
        }
        cursor.close();
        db.close();

        // return category list
        return listBillsDates;
    }

I believe that a query based upon :- 我相信基于:-的查询

SELECT sum(COLUMN_AMOUNT) AS Monthly_Total,substr(COLUMN_DATE_STRING,4) AS Month_and_Year
    FROM TABLE_BILLS 
    WHERE COLUMN_BILL_USER_ID = 1
  GROUP BY substr(COLUMN_DATE_STRING,4)
    ORDER BY substr(COLUMN_DATE_STRING,7,2)||substr(COLUMN_DATE_STRING,4,2)
;
  • Note that other columns values would be arbritary results and as such cannot really be relied upon (fine if the data is always the same). 请注意,其他列值将是计算结果,因此不能真正依赖(如果数据始终相同,则可以)。 Hence they have not been included. 因此,它们未被包括在内。

Will produce the results that you want :- 将产生您想要的结果:-

eg 例如

Using the following, to test the SQL :- 使用以下命令测试SQL:

DROP TABLE IF EXISTS TABLE_BILLS;
CREATE TABLE IF NOT EXISTS TABLE_BILLS (
    COLUMN_BILL_ID INTEGER PRIMARY KEY AUTOINCREMENT,
    COLUMN_BILL_USER_ID INTEGER,
    COLUMN_DESCRIPTION TEXT,
    COLUMN_AMOUNT INTEGER,
    COLUMN_DATE_STRING TEXT,
    COLUMN_COMPANY_NAME TEXT,
    COLUMN_CATEGORY TEXT)
    ;

-- Add the Testing data
INSERT INTO TABLE_BILLS (
    COLUMN_BILL_USER_ID, COLUMN_DESCRIPTION, COLUMN_AMOUNT, COLUMN_DATE_STRING, COLUMN_COMPANY_NAME,COLUMN_CATEGORY)
VALUES 
        (1,'blah',230,'04/03/19','cmpny','category')
        ,(1,'blah',500,'05/03/19','cmpny','category')
        ,(1,'blah',400,'04/04/19','cmpny','category')
        ,(1,'blah',600,'06/04/19','cmpny','category')
        ,(1,'blah',100,'04/03/19','cmpny','category')

        -- Extra data for another id to check exclusion
        ,(2,'blah',230,'04/03/19','cmpny','category')
        ,(2,'blah',500,'05/03/19','cmpny','category')
        ,(2,'blah',400,'04/04/19','cmpny','category')
        ,(2,'blah',600,'06/04/19','cmpny','category')
        ,(2,'blah',100,'04/03/19','cmpny','category')
;

SELECT sum(COLUMN_AMOUNT) AS Monthly_Total,substr(COLUMN_DATE_STRING,4) AS Month_and_Year
    FROM TABLE_BILLS 
    WHERE COLUMN_BILL_USER_ID = 1
  GROUP BY substr(COLUMN_DATE_STRING,4)
    ORDER BY substr(COLUMN_DATE_STRING,7,2)||substr(COLUMN_DATE_STRING,4,2)
;

Results id :- 结果编号:-

在此处输入图片说明

The above can then be converted for use by the SQLiteDatabase query method. 然后可以转换以上内容,以供SQLiteDatabase 查询方法使用。 So your method could be something like :- 因此,您的方法可能类似于:-

public ArrayList<Bills> getDateByUserID(int userID) {
    SQLiteDatabase db = this.getReadableDatabase();
    String tmpcol_monthly_total = "Monthly_Total";
    String tmpcol_month_year = "Month_and_Year";
    String[] columns = new String[]{
            "sum(" + COLUMN_AMOUNT + ") AS " + tmpcol_monthly_total,
            "substr(" + COLUMN_DATE_STRING + ",4) AS " + tmpcol_month_year
    };
    String whereclause = COLUMN_BILL_USER_ID + "=?";
    String[] whereargs = new String[]{String.valueOf(userID)};
    String groupbyclause = "substr(" + COLUMN_DATE_STRING + ",4)";
    String orderbyclause = "substr(" + COLUMN_DATE_STRING + ",7,2)||substr(" + COLUMN_DATE_STRING + ",4,2)";
    ArrayList<Bills> listBillsDates = new ArrayList<Bills>();

    Cursor cursor = db.query(TABLE_BILLS, columns, whereclause,
            whereargs, groupbyclause, null, orderbyclause, null);
    if (cursor.moveToFirst()) {
        do {
            Bills bills = new Bills();
            bills.setAmount(cursor.getInt(cursor.getColumnIndex(tmpcol_monthly_total)));
            bills.setDateString(cursor.getString(cursor.getColumnIndex(tmpcol_month_year))); //<<<<<<<<<< NOTE data is MM/YY (otherwise which date to use? considering result will be arbrirtaryy)
            // Adding record to list
            listBillsDates.add(bills);
        } while (cursor.moveToNext());
    }
    cursor.close();
    db.close();

    // return category list
    return listBillsDates;
}
  • The above has been tested and run and using the following code :- 上面的代码已经过测试和运行,并使用以下代码:-

     ArrayList<Bills> myMonthlyTotals = mDBHelper.getDateByUserID(1); Log.d("BILLSCOUNT","The number of bills extracted was " + String.valueOf(myMonthlyTotals.size())); for (Bills b: myMonthlyTotals) { Log.d("MONTHYLTOTAL","Monthly total for " + b.getDateString() + " was " + String.valueOf(b.getAmount())); } 
  • In an activity, resulted in the following in the log 在一个活动中,导致以下日志

:- : -

04-14 11:58:25.876 16653-16653/? D/BILLSCOUNT: The number of bills extracted was 2
04-14 11:58:25.877 16653-16653/? D/MONTHYLTOTAL: Monthly total for 03/19 was 830
04-14 11:58:25.877 16653-16653/? D/MONTHYLTOTAL: Monthly total for 04/19 was 1000
  • Please consider the comments in regard to values from non-aggreagted columns be arbitrary values. 请考虑有关非聚合列中的值的注释是任意值。 As per :- 按照 :-

  • Each non-aggregate expression in the result-set is evaluated once for an arbitrarily selected row of the dataset. 对于数据集的任意选择的行,结果集中的每个非聚合表达式都会被评估一次。 The same arbitrarily selected row is used for each non-aggregate expression. 相同的任意选择的行用于每个非聚合表达式。 Or, if the dataset contains zero rows, then each non-aggregate expression is evaluated against a row consisting entirely of NULL values. 或者,如果数据集包含零行,则将针对完全由NULL值组成的行评估每个非聚合表达式。 SELECT - 3. Generation of the set of result rows. 选择-3.生成结果行集。

As per the comments, using recognised date formats can make the underlying SQL simpler and likely more efficient. 根据注释,使用公认的日期格式可以使基础SQL更简单并且可能更有效率。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM