【问题标题】:Android : Calculate sum and group by month (SQLite)Android:按月计算总和和分组(SQLite)
【发布时间】:2019-04-14 10:10:41
【问题描述】:

是否有任何选项可以选择金额,按月分组并计算总和。我试图获取每个月的总和并将其传递给 ArrayList。
数据示例:

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

我的代码结构

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;
    }

【问题讨论】:

  • 第 1 步是以 sqlite 的日期和时间函数支持的格式之一存储您的日期。请参阅该列表here。
  • 完成此操作后,您可以在表达式上使用 strftime() GROUP BY 从时间戳中获取月份。

标签: java android sqlite


【解决方案1】:

我相信基于以下的查询:-

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)
;
  • 请注意,其他列的值将是任意结果,因此不能真正依赖(如果数据始终相同,则可以)。因此它们没有被包括在内。

会产生你想要的结果:-

例如

使用以下代码来测试 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)
;

结果编号:-

然后可以转换上述内容以供 SQLiteDatabase query 方法使用。所以你的方法可能是这样的:-

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;
}
  • 以上内容已经过测试和运行,并使用以下代码:-

    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()));
    
    }
    
  • 在一个活动中,导致日志中出现以下内容

:-

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
  • 请考虑与来自非聚合列的值有关的 cmets 是任意值。根据:-

  • 结果集中的每个非聚合表达式都会针对任意选择的数据集行进行一次评估。相同的任意选择的行用于每个非聚合表达式。或者,如果数据集包含零行,则每个非聚合表达式都会根据完全由 NULL 值组成的行进行评估。 SELECT - 3. Generation of the set of result rows.

根据 cmets,使用公认的 date formats 可以使底层 SQL 更简单,并且可能更高效。

【讨论】:

    猜你喜欢
    • 2017-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多