Я недавно боролся с этой проблемой, обращаясь к базе данных CallLog.Calls (где мы не смогли изменить ContentProvider).В итоге мы создали запрос, который выглядел следующим образом:
SELECT _id, date, duration, type, normalized_number FROM calls WHERE _id IN (
SELECT _id FROM calls WHERE date < ? GROUP BY normalized_number ORDER BY date DESC LIMIT ?
);
Идея в том, что мы помещаем любой допустимый sqlite в наш подзапрос, возвращаем список идентификаторов и затем снова запрашиваем все вызовы.с этими идентификаторами.
Конечный код выглядел примерно так:
String whereClause = "_id IN (SELECT _id FROM calls WHERE data < ? GROUP BY normalized_number ORDER BY date DESC LIMIT ?)";
Cursor cursor = context.getContentResolver().query(
CallLog.Calls.CONTENT_URI,
new String[] { "_id", "date", "duration", "normalized_number" },
whereClause,
new String[]{ String.valueOf(amount), String.valueOf(dateFrom) },
null
);
...
В случае, если вы запрашиваете контакты, он будет выглядеть примерно так:
String whereClause = "_id IN (SELECT _id FROM contacts WHERE " + Phone.NUMBER + " LIKE ? OR " + Email.DATA + " LIKE ? GROUP BY " + Data.RAW_CONTACT_ID + " ORDER BY lower(" + Data.DISPLAY_NAME + ") ASC)";
String[] params = new String["%test%", "%test%"];
Cursor cursor = getContentResolver().query(
Data.CONTENT_URI,
new String[] { Data._ID, Data.RAW_CONTACT_ID },
whereClause,
params,
null
);
Будет некоторое снижение производительности (так как мы по существу запрашиваем дважды для одинаковых результатов), но это, безусловно, будет намного быстрее, чем запросы для всех вызовов и выполнение работы GROUP BY
в мире Java, а такжепозволяет создать запрос с дополнительными предложениями.
Надеюсь, это поможет.Мы использовали это на Oreo, и это удовлетворило наши потребности.