如何计算已添加在一起的组的最大和最小

时间:2018-09-30 00:04:56

标签: java android sqlite

如何获得已分组并由_id相加的列的MAX值。

是这样的:

enter image description here

然后我要显示四组的MAX值,以及四组的MIN值。

类似的东西从零开始= 702 /从低点= 325

SQLite的内置Math函数是否可能实现此目的,或者我需要编写特定的代码来实现此目的?实际的组数将超过4组,这取决于投球手实际打系列的次数。

到目前为止,我还没有为此编写任何代码,我试图在尝试这样做之前,先弄清楚这是否可能。欢迎大家提出意见。 我尝试整合到我的项目中:

DatabaseHelper.java

public static final String DERIVEDCOL_MAXSCORE = "max_score";
    public static final String DERIVEDCOl_MINSCORE = "min_score";

    public Cursor getMaxMinScoresAllAndroid() {

            SQLiteDatabase db = this.getWritableDatabase();

            String tmptbl = "summed_scores";
            String tmptblcol = "sum_score";

            String crttmptbl = "CREATE TEMP TABLE IF NOT EXISTS " + tmptbl + "(" +
                    tmptblcol + " INTEGER" +
                    ")";
            String empttmptbl = "DELETE FROM " + tmptbl;

            db.execSQL(crttmptbl);
            db.execSQL(empttmptbl);
            String[] columns = new String[]{"sum(score) AS " + tmptblcol};
            Cursor csr = db.query(Game.TABLE_NAME,columns,null,null,Game.COLUMN_BOWLER_ID,null,null);
            DatabaseUtils.dumpCursor(csr);
            while (csr.moveToNext()) {
                ContentValues cv = new ContentValues();
                cv.put(tmptblcol,csr.getInt(csr.getColumnIndex(tmptblcol)));
                db.insert(tmptbl,null,cv);
            }
            csr.close();

            columns = new String[]{"max(" +
                    tmptblcol +
                    ") AS " + DERIVEDCOL_MAXSCORE,
                    "min(" +
                            tmptblcol +
                            ") AS " + DERIVEDCOl_MINSCORE};
            return csr = db.query(tmptbl,columns,null,null,null,null,null);
        }

        public MaxMin getMaxAndminScoresAll() {
            MaxMin rv = new MaxMin(0,0);
            Cursor csr = getMaxMinScoresAllAndroid();
            if (csr.moveToFirst()) {
                rv.setMin(csr.getInt(csr.getColumnIndex(DERIVEDCOl_MINSCORE)));
                rv.setMax(csr.getInt(csr.getColumnIndex(DERIVEDCOL_MAXSCORE)));
            }
            csr.close();
            return rv;
        }

BowlerProfileViewActivity.java

public class BowlerProfileViewActivity extends AppCompatActivity {

    Bowler bowler;

    private DatabaseHelper db;

    private static final String PREFS_NAME = "prefs";
    private static final String PREF_BLUE_THEME = "blue_theme";
    private static final String PREF_GREEN_THEME = "green_theme";
    private static final String PREF_ORANGE_THEME = "purple_theme";
    private static final String PREF_RED_THEME = "red_theme";
    private static final String PREF_YELLOW_THEME = "yellow_theme";

    @Override
    protected void onResume() {
        super.onResume();
        db = new DatabaseHelper(this);
        //mAdapter.notifyDatasetChanged(db.getAllLeagues());
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        //Use Chosen Theme
        SharedPreferences preferences = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
        boolean useBlueTheme = preferences.getBoolean(PREF_BLUE_THEME, false);
        if (useBlueTheme) {
            setTheme(R.style.AppTheme_Blue_NoActionBar);
        }
        boolean useGreenTheme = preferences.getBoolean(PREF_GREEN_THEME, false);
        if (useGreenTheme) {
            setTheme(R.style.AppTheme_Green_NoActionBar);
        }
        boolean useOrangeTheme = preferences.getBoolean(PREF_ORANGE_THEME, false);
        if (useOrangeTheme) {
            setTheme(R.style.AppTheme_Orange_NoActionBar);
        }
        boolean useRedTheme = preferences.getBoolean(PREF_RED_THEME, false);
        if (useRedTheme) {
            setTheme(R.style.AppTheme_Red_NoActionBar);
        }
        boolean useYellowTheme = preferences.getBoolean(PREF_YELLOW_THEME, false);
        if (useYellowTheme) {
            setTheme(R.style.AppTheme_Yellow_NoActionBar);
        }

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bowler_profile_view);

        Intent intent = getIntent();
        Boolean shouldUpdate = getIntent().getExtras().getBoolean("shouldUpdate");
        String savedLeagueId = intent.getStringExtra("leagueId");
        String savedBowlerId = String.valueOf(getIntent().getIntExtra("bowlerId",2));
        int bowlerId = Integer.valueOf(savedBowlerId);

        getBowlerProfile(savedLeagueId, bowlerId);

        // Get The min and max score
        MaxMin bowlerMaxMin =  db.getMaxAndminScoresAll();
        Log.d("SCORES",
                "\n\tMaximum Score is " + String.valueOf(bowlerMaxMin.getMax()) +
                        "\n\tMinimum Score is " + String.valueOf(bowlerMaxMin.getMin()));

    }

    public void getBowlerProfile(String savedLeagueId, int savedBowlerId) {

        String bn, ba, bh;

        SQLiteOpenHelper database = new DatabaseHelper(this);
        SQLiteDatabase db = database.getReadableDatabase();

        Cursor viewBowlerProfile = db.query( Bowler.TABLE_NAME,
                new String[]{Bowler.COLUMN_ID, Bowler.COLUMN_LEAGUE_ID, Bowler.COLUMN_NAME, Bowler.COLUMN_BOWLER_AVERAGE, Bowler.COLUMN_BOWLER_HANDICAP, Bowler.COLUMN_TIMESTAMP},
                Bowler.COLUMN_ID + "=?",
                new String[]{String.valueOf(savedBowlerId)}, null, null, null, null);

        if (viewBowlerProfile.moveToFirst()) {

            //Prepare League Object
            bowler = new Bowler(
                    viewBowlerProfile.getInt(viewBowlerProfile.getColumnIndex(Bowler.COLUMN_ID)),
                    viewBowlerProfile.getString(viewBowlerProfile.getColumnIndex(Bowler.COLUMN_LEAGUE_ID)),
                    bn = viewBowlerProfile.getString(viewBowlerProfile.getColumnIndex(Bowler.COLUMN_NAME)),
                    ba = viewBowlerProfile.getString(viewBowlerProfile.getColumnIndex(Bowler.COLUMN_BOWLER_AVERAGE)),
                    bh = viewBowlerProfile.getString(viewBowlerProfile.getColumnIndex(Bowler.COLUMN_BOWLER_HANDICAP)),
                    viewBowlerProfile.getString(viewBowlerProfile.getColumnIndex(Bowler.COLUMN_TIMESTAMP)));

            final TextView bowlerName = (TextView) findViewById(R.id.tvBowlerName);
            final TextView bowlerAverage = (TextView) findViewById(R.id.tvBowlerAverageValue);
            final TextView bowlerHandicap = (TextView) findViewById(R.id.tvBowlerHandicapValue);

            bowlerName.setText(String.valueOf(bn));
            bowlerAverage.setText(String.valueOf(ba));
            bowlerHandicap.setText(String.valueOf(bh));

            //Close Database Connection
            viewBowlerProfile.close();
        }

        //View League Profile Cancel Button
        final Button cancel_button = (Button) findViewById(R.id.bCancel);
        cancel_button.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {
                Log.d("SAVEDLEAGUEID_VAL", ">>" + String.valueOf(savedLeagueId) + "<<");
                Intent intent = new Intent(getApplicationContext(), BowlerActivity.class);
                intent.putExtra("leagueId", savedLeagueId);
                startActivity(intent);
                finish();
                overridePendingTransition(0, 0);
                /*Intent intent = new Intent(getApplicationContext(), BowlerActivity.class);
                intent.putExtra("leagueId", savedLeagueId);
                Log.d("LEAGUEID VALUE","value of leagueId = " + String.valueOf(savedLeagueId));
                startActivity(intent);
                finish();
                overridePendingTransition(0, 0);*/
            }

        });

        //Edit League Profile Cancel Button
        final Button edit_button = (Button) findViewById(R.id.bEdit);
        edit_button.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {
                int bowlerId = bowler.getId();
                Intent intent = new Intent(getApplicationContext(), BowlerProfileEditActivity.class);
                intent.putExtra("bowlerId", bowlerId);
                intent.putExtra("leagueId", savedLeagueId);
                startActivity(intent);
                finish();
                overridePendingTransition(0, 0);
            }

        });
    }
}

Logcat

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'ca.rvogl.tpbcui.utils.MaxMin ca.rvogl.tpbcui.database.DatabaseHelper.getMaxAndminScoresAll()' on a null object reference
        at ca.rvogl.tpbcui.views.BowlerProfileViewActivity.onCreate(BowlerProfileViewActivity.java:79)
        at android.app.Activity.performCreate(Activity.java:6679)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)

尝试按BowlerId和seriesId分组

public Cursor getMaxMinScoresAllAndroid(String bowlerId) {

    SQLiteDatabase db = this.getWritableDatabase();

    String tmptbl = "summed_scores";
    String tmptblcol = "sum_score";
    String tmpBowlerIdCol = "bowler_id";
    String tmpSeriesIdCol = "series_id";

    String crttmptbl = "CREATE TEMP TABLE IF NOT EXISTS " + tmptbl + "(" +
            tmptblcol + " INTEGER," + 
            tmpBowlerIdCol + " TEXT," + 
            tmpSeriesIdCol + " TEXT)";
    String empttmptbl = "DELETE FROM " + tmptbl;

    db.execSQL(crttmptbl);
    db.execSQL(empttmptbl);
    String[] columns = new String[]{"sum(score) AS "};
    Cursor csr = db.query(Game.TABLE_NAME,columns,null,null,Game.COLUMN_BOWLER_ID + " = '" + bowlerId + "'", Game.COLUMN_SERIES_ID,null,null);
    DatabaseUtils.dumpCursor(csr);
    while (csr.moveToNext()) {
        ContentValues cv = new ContentValues();
        cv.put(tmptblcol,csr.getInt(csr.getColumnIndex(tmptblcol)));
        cv.put(tmpBowlerIdCol,csr.getInt(csr.getColumnIndex(tmpBowlerIdCol)));
        cv.put(tmpSeriesIdCol,csr.getInt(csr.getColumnIndex(tmpSeriesIdCol)));
        db.insert(tmptbl,null,cv);
    }
    csr.close();

    columns = new String[]{"max(" +
            tmptblcol +
            ") AS " + DERIVEDCOL_MAXSCORE,
            "min(" +
                    tmptblcol +
                    ") AS " + DERIVEDCOl_MINSCORE};
    return csr = db.query(tmptbl,columns,null,null,null,null,null);
}

public MaxMin getMaxAndminScoresAll(String bowlerId) {
    MaxMin rv = new MaxMin(0,0);
    Cursor csr = getMaxMinScoresAllAndroid(bowlerId);
    if (csr.moveToFirst()) {
        rv.setMin(csr.getInt(csr.getColumnIndex(DERIVEDCOl_MINSCORE)));
        rv.setMax(csr.getInt(csr.getColumnIndex(DERIVEDCOL_MAXSCORE)));
    }
    csr.close();
    return rv;
}

1 个答案:

答案 0 :(得分:2)

您可以执行以下操作(假设表名为 myscores ,列为 _id 得分),请使用:-

WITH cte1 AS 
    (
        sum(score) AS sum_score
        FROM myscores
        GROUP BY _id
    )
SELECT max(sum_score) AS min_score, min(sum_score) FROM cte1;

使用此方法将导致以下结果:-

enter image description here

这利用SQLite聚合函数 max min 以及GROUP BY子句根据_id列聚合列。

这也利用了公共表表达式(中间/临时表)。 SQL As Understood By SQLite - WITH clause


集成到Android应用程序中(请参阅末尾的注释)

以下是一个示例应用程序,演示了如何将其合并到Android中:-

首先是用于最小和最大价位的简单类(如在可选的getMaxAndMinScores方法中使用的那样)

MaxMin.java(可选)

public class MaxMin {

    private int min;
    private int max;

    public MaxMin(int min, int max) {
        this.min = min;
        this.max = max;
    }

    public int getMin() {
        return min;
    }

    public void setMin(int min) {
        this.min = min;
    }

    public int getMax() {
        return max;
    }

    public void setMax(int max) {
        this.max = max;
    }
}

DBHelper.java

SQLiteOpenHelper的子类(只是一个表名myscores)

public class DBHelper extends SQLiteOpenHelper {

    public static final String DBNAME = "mydb";
    public static final int DBVERSION = 1;
    public static final String TB_SCORE = "myscores";
    public static final String COL_SCORE = "score";
    public static final String COL_ID = BaseColumns._ID;

    public static final String DERIVEDCOL_MAXSCORE = "max_score";
    public static final String DERIVEDCOl_MINSCORE = "min_score";

    private static final String crt_myscores_sql = "CREATE TABLE IF NOT EXISTS " + TB_SCORE + "(" +
            COL_ID + " INTEGER," +
            COL_SCORE + " INTEGER" +
            ")";

    public DBHelper(Context context) {
        super(context, DBNAME, null, DBVERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(crt_myscores_sql);

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int i, int i1) {

    }

    public long addScore(long id, int score) {
        ContentValues cv = new ContentValues();
        cv.put(COL_ID,id);
        cv.put(COL_SCORE,score);
        return this.getWritableDatabase().insert(TB_SCORE,null,cv);
    }

    public Cursor getMaxMinScores() {
        String sum_score = "sum_score";
        String cte1 = "cte1";
        String rawqry = " WITH " + cte1 +
                " AS " +
                "(" +
                "SELECT sum(" +
                COL_SCORE +
                ") AS " + sum_score +
                " FROM " + TB_SCORE + " GROUP BY " + COL_ID +
                ") " +
                "SELECT " +
                " max(" +
                sum_score +
                ") AS " + DERIVEDCOL_MAXSCORE +
                "," +
                " min(" +
                sum_score +
                ") AS " + DERIVEDCOl_MINSCORE +
                " FROM " + cte1 + ";";
        return this.getWritableDatabase().rawQuery(rawqry,null);
    }

    public MaxMin getMaxAndMinScores() {
        MaxMin rv = new MaxMin(0,0);
        Cursor csr = getMaxMinScores();
        if (csr.moveToFirst()) {
            rv.setMin(csr.getInt(csr.getColumnIndex(DERIVEDCOl_MINSCORE)));
            rv.setMax(csr.getInt(csr.getColumnIndex(DERIVEDCOL_MAXSCORE)));
        }
        csr.close();
        return rv;
    }
}

MainActivity.java

a)添加一些行,然后b)获得最大和最小分数(使用替代方法两次)的活动:-

public class MainActivity extends AppCompatActivity {

    DBHelper mDBHlpr;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mDBHlpr = new DBHelper(this);
        // Add Some scores
        mDBHlpr.addScore(1,112);
        mDBHlpr.addScore(1,123);
        mDBHlpr.addScore(1,144);
        mDBHlpr.addScore(2,212);
        mDBHlpr.addScore(2,190);
        mDBHlpr.addScore(2,300);
        mDBHlpr.addScore(3,234);
        mDBHlpr.addScore(3,134);
        mDBHlpr.addScore(3,122);
        mDBHlpr.addScore(4,100);
        mDBHlpr.addScore(4,111);
        mDBHlpr.addScore(4,114);

        // Get The min and max scores example 1
        Cursor csr = mDBHlpr.getMaxMinScores();
        if (csr.moveToFirst()) {
            int max_score = csr.getInt(csr.getColumnIndex(DBHelper.DERIVEDCOL_MAXSCORE));
            int min_score = csr.getInt(csr.getColumnIndex(DBHelper.DERIVEDCOl_MINSCORE));
            Log.d("SCORES",
                    "\n\tMaximum Score is " + String.valueOf(max_score) +
                            "\n\tMinimum Score is " + String.valueOf(min_score)
            );
        }

        //Alternative utilising the MaxMin object
        MaxMin mymaxmin =  mDBHlpr.getMaxAndMinScores();
        Log.d("SCORES",
                "\n\tMaximum Score is " + String.valueOf(mymaxmin.getMax()) +
                        "\n\tMinimum Score is " + String.valueOf(mymaxmin.getMin())
        );
    }
}

重要

  

WITH子句是SQL 3.8.3中引入的,某些旧版Android(低于Lollipop(但可以与设备无关))不会   支持WITH子句。

以下方法(与getMaxMinScoresgetMaxAndMinScores等效)可用于任何Android版本:-

public Cursor getMaxMinScoresAllAndroid() {

    SQLiteDatabase db = this.getWritableDatabase();

    String tmptbl = "summed_scores";
    String tmptblcol = "sum_score";

    String crttmptbl = "CREATE TEMP TABLE IF NOT EXISTS " + tmptbl + "(" +
            tmptblcol + " INTEGER" +
            ")";
    String empttmptbl = "DELETE FROM " + tmptbl;

    db.execSQL(crttmptbl);
    db.execSQL(empttmptbl);
    String[] columns = new String[]{"sum(score) AS " + tmptblcol};
    Cursor csr = db.query(TB_SCORE,columns,null,null,COL_ID,null,null);
    DatabaseUtils.dumpCursor(csr);
    while (csr.moveToNext()) {
        ContentValues cv = new ContentValues();
        cv.put(tmptblcol,csr.getInt(csr.getColumnIndex(tmptblcol)));
        db.insert(tmptbl,null,cv);
    }
    csr.close();

    columns = new String[]{"max(" +
            tmptblcol +
            ") AS " + DERIVEDCOL_MAXSCORE,
            "min(" +
                    tmptblcol +
                    ") AS " + DERIVEDCOl_MINSCORE};
    return csr = db.query(tmptbl,columns,null,null,null,null,null);
}

public MaxMin getMaxAndminScoresAllAndroid() {
    MaxMin rv = new MaxMin(0,0);
    Cursor csr = getMaxMinScoresAllAndroid();
    if (csr.moveToFirst()) {
        rv.setMin(csr.getInt(csr.getColumnIndex(DERIVEDCOl_MINSCORE)));
        rv.setMax(csr.getInt(csr.getColumnIndex(DERIVEDCOL_MAXSCORE)));
    }
    csr.close();
    return rv;
}
  • 这些利用中间临时表,因此绕过了使用 WITH
  • 的限制