19

(LEFT은 가입 및 CASE) : 나는 시스템의 주소록에있는 모든 연락처의 ID와 이름을 선택 찾고ContentResolver.query()로이 Android 쿼리를 수행 할 수 있습니까? 안드로이드에 내가 (의사 코드) 다음 쿼리를 수행하기 위해 찾고 있어요

SELECT C.ID, C.NAME, CASE ISNULL(G.GROUPID,0) = 0 THEN 0 ELSE 1 END INGROUP 
FROM CONTACTS C 
LEFT JOIN GROUPMEMBERSHIP G ON G.CONTACTID = C.ID AND G.GROUPID = ? 

, 연락처가 그룹 ?의 멤버인지 여부를 나타내는 0/1 필드와 함께 기본 연락처 ContentProvider를 통해 전달됩니다.

물론 모든 연락처를 충분히 쉽게 가져올 수 있으며 루프를 통과하고 어댑터 클래스에서 멤버를 쉽게 쉽게 쿼리 할 수 ​​있습니다. 그러나 두 개의 쿼리를 하나의 외부 조인 된 쿼리로 수행하면 훨씬 우수한 성능을 얻을 수 있다고 생각합니다.

표준 고급 수준의 문자열 프로젝션과 ContentResolver.query() 방법으로이 작업을 수행 할 수 있습니까? 또는 이러한 종류의 쿼리는보다 직접적인 SQL 실행을 필요로합니까?

답변

7

아니요, 아니요. ContentResolver.query() 메소드로는 그런 종류의 쿼리를 수행 할 수 없습니다. 이 같은 것을 작성해야합니다

query(Uri uri, String[] projection, String selection, 
String[] selectionArgs, String sortOrder) 

테이블 또는 FROM 절에는 매개 변수가 없습니다 :

SQLiteDatabase db = YourActivity.getDbHelper().getReadableDatabase(); 
String query = yourLongQuery; 
Cursor c = db.rawQuery(query, null); 
YourActivity.startManagingCursor(c); 
c.setNotificationUri(YourActivity.getContentResolver(), YourContentProvider.CONTENT_URI); 
+0

주위를 검색 할 때 SQLLiteDatabase를 다른 응용 프로그램을 쿼리하는 데 사용할 수 없다는 인상을받습니다. 제 경우에는 CONTACTS URI가 있지만 자신의 데이터 저장소를 쿼리 할 때만 사용할 수 있습니다. 이 올바른지? 어떤 경우에는 내 활동을 바인딩 할 때 어댑터 클래스에서 하위 쿼리를 수행하는 데 어려움을 겪을 것입니다. – eidylon

+0

@eidylon : 연락처 db를 쿼리하고 있다는 사실을 알지 못했습니다. 네, 맞습니다 :( – Macarse

+0

Drat! Oh ... 음 ... 앞으로 그리고 위쪽으로! 감사합니다! – eidylon

0

당신은 컨텐트 리졸버는 하나의 쿼리 방법을 가지고 있기 때문에 그렇게 할 수 없습니다.

41

편집 :그래,이 질문은 실제로 질문을 해결하지 않습니다. 왜냐하면 eidylon은 질문에서 언급 한 것처럼 기존 ContentProvider에 묶여 있기 때문입니다. 그러나 ContentProvider 소스 및 API를 소유하고있는 경우 JOIN을 수행하는 방법에 대해 설명합니다. 그래서 나는 그 사건을 어떻게 다룰지를 알고 싶어하는 사람들을 위해서 맡길 것이다.


이것은 쉽습니다! 하지만 unintuitive ... :)

query(Uri uri, String[] projection, String selection, 
String[] selectionArgs, String sortOrder) 

좋아요, 그렇다면 URI는 무엇인가요? 일반적으로 테이블 당 하나의 URI가 있습니다.

content://com.example.coolapp.contactsCONTACTS 테이블의 데이터를 제공합니다. content://com.example.coolapp.groupmembersGROUPMEMBERSHIP 테이블의 데이터를 제공합니다.

하지만 URI는 실제로는 문자열입니다. 원하는대로 사용하십시오. ContentProvider에서 content://com.example.coolapp.contacts_in_group에 응답하는 코드 블록을 만듭니다. ContentProvider에있는 해당 코드 블록 내에서 한정된 query() 데이터 모델에 의해 자유롭게 SQLite DB에 원시 액세스 할 수 있습니다. 부담없이 사용하십시오!

원하는 선택 필드를 정의하십시오. 그들은 에 테이블 열 이름에 매핑 할이 없습니다. 매개 변수를 가져 오려면 필요한 방법을 매핑하십시오.

필요에 따라 투영법을 정의하십시오. - 두 테이블의 열을 모두 포함 할 수 있습니다. 조인

빙, 끝났습니다. Google은 내부적으로이 코드를 내부 코드로 처리합니다. 주소록 제공자 API를 살펴보십시오. "bla.RawContact"및 "bla.Contact"등이 콘텐츠 URI로 표시됩니다.각각은 DB의 동일한 테이블에서 데이터를 제공합니다. 다른 URI는 동일한 테이블의 다른 을 제공합니다.

+0

대답 해 주셔서 감사합니다 ... 매우 상세하고 유익한 내용이므로 upvoted,하지만 분명히 *** *** 내 Q에서 불분명했습니다. 내가 안드로이드 연락처 DB를 쿼리하고, 내 자신의 DB가 아니었다. 당신이 이것을 놓친 유일한 사람이 아니 었어. 나는 그것에 대해 좀 더 명확하게 내 말을 업데이 트했습니다. 감사합니다! :) – eidylon

+1

죄송합니다, 예. 기존의 contactProvider를 사용하는 경우 구현 된 모든 콘텐츠 URI와 조인이 붙어 있습니다. – jcwenger

+0

이렇게 합쳐서 ContentProvider에서 "query"메서드를 재정의하고 URI를 확인한 다음 SQLite db에 직접 연결하여 원하는 작업을 수행 하시겠습니까? 감사! –

관련 문제