[英]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)
;
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.