2

私は SMS アプリケーションを開発しています。各会話から最後の SMS を取得しようとしています。

これが私のSQLステートメントです:

SELECT MAX(smsTIMESTAMP) AS smsTIMESTAMP,_id, smsID, smsCONID, smsMSG, smsNUM, smsREAD, smsTYPE, smsSHORTMSG, COUNT(*) AS smsNUMMESSAGES FROM sms GROUP BY smsCONID ORDER BY smsTIMESTAMP desc

SQLite Expert でクエリを実行したところ、正しい応答が得られました。

ここに画像の説明を入力

ただし、アプリで実行すると、次のようになります。

ここに画像の説明を入力

これが私のテーブルです

ここに画像の説明を入力

ここに私の Datamanipulator クラスがあります:

public class DataManipulator {
    private static final  String DATABASE_NAME = "smsapplication.db";
    private static final int DATABASE_VERSION = 3;
    static final String TABLE_NAME = "sms";
    private static Context context;
    static SQLiteDatabase db;
    private static DataManipulator instance;

    private SQLiteStatement insertStmt;

    private static final String INSERT = "insert or ignore into "
        + TABLE_NAME + " (smsID, smsCONID, smsMSG, smsNUM, smsREAD, smsTIMESTAMP, smsTYPE, smsSHORTMSG) values (?,?,?,?,?,?,?,?)";

    public DataManipulator(Context context) {
        DataManipulator.context = context;
        OpenHelper openHelper = new OpenHelper(DataManipulator.context);
        DataManipulator.db = openHelper.getWritableDatabase();
        this.insertStmt = DataManipulator.db.compileStatement(INSERT);
    }
    public static DataManipulator getInstance(Context mContext)
    {
        if(instance == null)
        {
            instance = new DataManipulator(mContext);
        }
        return instance;
    }
    public long insert(int smsID, int smsCONID, String smsMSG,
            String smsNUM, int smsREAD, long smsTIMESTAMP, String smsTYPE, String smsSHORTMSG) {
        this.insertStmt.bindLong(1, smsID);
        this.insertStmt.bindLong(2, smsCONID);
        this.insertStmt.bindString(3, smsMSG);
        this.insertStmt.bindString(4, smsNUM);
        this.insertStmt.bindLong(5, smsREAD);
        this.insertStmt.bindString(6, String.valueOf(smsTIMESTAMP));
        this.insertStmt.bindString(7, smsTYPE);
        this.insertStmt.bindString(8, smsSHORTMSG);
        return this.insertStmt.executeInsert();
    }

    public void deleteAll() {
        db.delete(TABLE_NAME, null, null);
    }

    public Cursor getLastSmsForAllConversations()
    {
        Cursor cursor = db.query(TABLE_NAME, new String[] {"_id"," MAX(smsTIMESTAMP) AS smsTIMESTAMP ", "smsCONID", "smsNUM", "smsREAD", "smsTYPE","smsSHORTMSG","COUNT(*) AS smsNUMMESSAGES"  },
                null, null, "smsCONID", null, "smsTIMESTAMP desc"); 
        return cursor;
    }
    public Cursor getConversationMessages(int conID)
    {
        Cursor cursor = db.query(TABLE_NAME, new String[] {"_id", "smsID", "smsCONID", "smsMSG", "smsNUM", "smsREAD", "smsTIMESTAMP", "smsTYPE","smsSHORTMSG"  },
                "smsCONID="+conID, null, null, null, "smsTIMESTAMP asc"); 
        return cursor;
    }
    public void printCursor()
    {
        Cursor cursor = db.rawQuery("SELECT MAX(smsTIMESTAMP) AS smsTIMESTAMP,_id, smsID, smsCONID, smsMSG, smsNUM, smsREAD, smsTYPE, smsSHORTMSG, COUNT(*) AS smsNUMMESSAGES FROM sms GROUP BY smsCONID ORDER BY smsTIMESTAMP desc", null);

            //  db.query(TABLE_NAME, new String[] {"_id","smsTIMESTAMP AS smsTIMESTAMP ", "smsCONID", "smsNUM", "smsREAD", "smsTYPE","smsSHORTMSG"  },"smsCONID=40", null, null, null, "smsTIMESTAMP desc");  
        if (cursor.moveToFirst()){
               do{
                  String data ="";
                  data= cursor.getString(cursor.getColumnIndex("smsTIMESTAMP"))+" - " +cursor.getString(cursor.getColumnIndex("smsSHORTMSG"));
                  Log.i("data", data);
               }while(cursor.moveToNext()); 
            }
            cursor.close();
    }

    private static class OpenHelper extends SQLiteOpenHelper {

        OpenHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL("CREATE TABLE " + TABLE_NAME + " (_id INTEGER , smsID INTEGER PRIMARY KEY, smsCONID INTEGER, smsMSG TEXT,smsNUM TEXT, smsREAD INTEGER, smsTIMESTAMP INTEGER, smsTYPE TEXT, smsSHORTMSG TEXT)");
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
            onCreate(db);
        }
         @Override
            public synchronized void close() {

            if (db != null)
                db.close();

            super.close();

            }
    } 
}
4

2 に答える 2

2

を使用している場合GROUP BY、結果の各行は元のテーブルの複数の行に対応します。これらの結果の計算方法には、次の 3 つの可能性があります。

  • グループ内のすべての行から値を計算する、MAXまたは計算するなどの集計関数を持つ列。COUNT
  • GROUP BY句に表示される列は、グループ内の任意のレコードから取得されます (グループ内のすべてのレコードがその列に対して同じ値を持つため)。
  • グループ内の行には異なる値が含まれている可能性があるため、他の列は問題になります。標準 SQL では、そのような列は禁止されています。SQLite はそれらを許可しますが、グループ内のランダムな行から値を与えるだけであり、これはあなたが望むものではありません。SQLite 3.7.11 から、MINまたはMAX;に一致する行から値を取得します。これは SQLite Expret で見られるものですが、古い SQLite を使用する Android では見られません。

問題を解決するには、最初に a を使用して、GROUP BY必要なレコードを識別するのに十分な情報を取得する必要があります。

SELECT smsCONID,                            -- OK: used in GROUP BY
       MAX(smsTIMESTAMP) AS smsTIMESTAMP,   -- OK: aggregate MAX
       COUNT(*) AS smsNUMMESSAGES           -- OK: aggregate COUNT
FROM sms
GROUP BY smsCONID
ORDER BY smsTIMESTAMP DESC

次に、その結​​果テーブルを元のsmsテーブルと結合して、これらのレコードの他の列を取得します。

SELECT *
FROM (SELECT smsCONID,
             MAX(smsTIMESTAMP) AS smsTIMESTAMP,
             COUNT(*) AS smsNUMMESSAGES
      FROM sms
      GROUP BY smsCONID) AS grouped
     JOIN sms
       ON grouped.smsCONID     = sms.smsCONID
      AND grouped.smsTIMESTAMP = sms.smsTIMESTAMP
ORDER BY smsTIMESTAMP DESC
于 2012-12-18T11:20:29.427 に答える
0

あなたのクエリとコードは正しいです。上記のクエリの代わりに問題は見つかりませんでした..

SELECT _id, smsID, smsCONID, smsMSG, smsNUM, smsREAD, smsTYPE, smsSHORTMSG, FROM sms GROUP BY smsCONID ORDER BY smsTIMESTAMP desc LIMIT 1

あなたもカウントしたい場合は、これを行います..

SELECT COUNT(*) AS smsNUMMESSAGES, _id, smsID, smsCONID, smsMSG, smsNUM, smsREAD, smsTYPE, smsSHORTMSG, FROM sms GROUP BY smsCONID ORDER BY smsTIMESTAMP desc LIMIT 1

于 2012-12-17T15:08:26.623 に答える