How to sort a two different cursor list?

Temuujin :

I want to sort the results coming from two cursors. Let's consider two different cursors to be Cursor and Cursor1.

Cursor is from CallLog.Call.CONTENT_URI and Cursor1 is from Telephony.Sms.CONTENT_URI.

The problem is two cursors combined list is sorting two different ways. I want to sort this combined list using date columns. Sorry for my bad English.

Here is my LogManager.java

public List<CallLogModel> getLogs() {
        List<CallLogModel> logObjectList;
        logObjectList = new ArrayList<>();

        Cursor cursor = this.context.getContentResolver().query(CallLog.Calls.CONTENT_URI,null, null, null, CallLog.Calls.DATE + " DESC ");
        Cursor cursor1 = this.context.getContentResolver().query(Telephony.Sms.CONTENT_URI, null, null, null, Telephony.Sms.DATE + " DESC ");

        // ------ Call Log ------
        int number = Objects.requireNonNull(cursor).getColumnIndex("number");
        int type = cursor.getColumnIndex("type");
        int date = cursor.getColumnIndex("date");
        int duration = cursor.getColumnIndex("duration");
        // ------ Call Log end ------

        // ------ SMS Log ------    
        int smsDate = Objects.requireNonNull(cursor1).getColumnIndexOrThrow(Telephony.Sms.DATE);
        int smsNumber = cursor1.getColumnIndexOrThrow(Telephony.Sms.ADDRESS);
        int smsType = cursor1.getColumnIndexOrThrow(Telephony.Sms.TYPE);
        // ------ SMS Log end ------

        while(cursor.moveToNext() && cursor1.moveToNext()) {
            CallLogModel log = new CallLogModel(this.context);
            // ------ Call Log ------
            log.setNumber(cursor.getString(number));
            log.setType(cursor.getInt(type));
            log.setDuration(cursor.getInt(duration));
            log.setDate(cursor.getLong(date));
            // ------ Call Log end ------

            // ------ SMS Log ------ 
            log.setAddress(cursor1.getString(smsNumber));
            log.setSmsDate(cursor1.getLong(smsDate));
            log.setSmsType(cursor1.getInt(smsType));
            logObjectList.add(log);.
            // ------ SMS Log end ------
        }
        cursor.close();
        cursor1.close();
        return logObjectList;
    }
MikeT :

Assuming that the date column is an integer (or a recognised SQLite datetime string SQL As Understood By SQLite - Date And Time Functions), then based upon the available information the following underlying query may do as you wish and the single result set means that you have a single cursor.

WITH combined AS (SELECT * FROM Calls UNION SELECT address, type, date, 0 FROM SMS)
SELECT * FROM combined ORDER BY date DESC;

This combines (makes a UNION) both tables (using 0 as the duration for SMS's (union requires both to have the same number of columns, hence the addition of 0)) and orders the combined list according to the date column.

Example

The following

  1. Deletes the tables if they exist for rerun-ability.
  2. Creates tables (based upon the columns that likely exist (names may well be different))
  3. Loads some data into the Calls table.
  4. loads some data into the SMS table (with times interspersed into the call times)
  5. SELECTS rows from each table (with an extra derived column that shows the date in an easy to read format)
  6. Finally invokes the query as above.

:-

DROP TABLE IF EXISTS Calls;
DROP TABLE IF EXISTS SMS;
/*
        int number = Objects.requireNonNull(cursor).getColumnIndex("number");
        int type = cursor.getColumnIndex("type");
        int date = cursor.getColumnIndex("date");
        int duration = cursor.getColumnIndex("duration");
*/
CREATE TABLE IF NOT EXISTS Calls (number INTEGER, type INTEGER, date INTEGER, duration INTEGER);
/*
        int smsDate = Objects.requireNonNull(cursor1).getColumnIndexOrThrow(Telephony.Sms.DATE);
        int smsNumber = cursor1.getColumnIndexOrThrow(Telephony.Sms.ADDRESS);
        int smsType = cursor1.getColumnIndexOrThrow(Telephony.Sms.TYPE);
*/
CREATE TABLE IF NOT EXISTS SMS (address INTEGER, date INTEGER, type INTEGER);

INSERT INTO Calls VALUES
    (1000000001,100,strftime('%s','now','+1 minutes'),30),
    (1000000002,100,strftime('%s','now','+3 minutes'),30),
    (1000000003,100,strftime('%s','now','+4 minutes'),30),
    (1000000004,100,strftime('%s','now','+6 minutes'),30),
    (1000000005,100,strftime('%s','now','-7 minutes'),30)
;

INSERT INTO SMS VALUES
    (2000000011,strftime('%s','now','+2 minutes'),200) /* Should be between call 1 and call 2 */, 
    (2000000012,strftime('%s','now','-12 minutes'),200) /* Should be after call 1 (when sorted with DESC) */,
    (2000000013,strftime('%s','now','+5 minutes'),200) /* between call 3 and 4 */,
    (2000000014,strftime('%s','now','+6 minutes'),200) /* same as call4 ? may be before or after unless ORDER BY is more comprehensive */
;

SELECT *,datetime(date,'unixepoch') AS easytoreaddatetime FROM Calls;
SELECT *,datetime(date,'unixepoch') AS easytoreaddatetime FROM SMS;

/*<<<<<<<<<< THE QUERY >>>>>>>>>>*/
WITH combined AS (SELECT * FROM Calls UNION SELECT address, type, date, 0 FROM SMS)
SELECT *, datetime(date,'unixepoch') FROM combined ORDER BY date DESC;

Results

1. The Calls table + datetime in easy to read format

enter image description here

2. The SMS table + datetime in easy read format

enter image description here

3. The combined, sorted list

enter image description here

  • Note The SMS rows are highlighted (they start with 2 not 1)
  • An easy to read data and time has also been added for the demo.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=327090&siteId=1