web-dev-qa-db-fra.com

Comment joindre deux tables SQLite dans mon application Android?

Contexte

J'ai un projet Android qui possède une base de données avec deux tables: tbl_question et tbl_alternative.

Pour remplir les vues avec des questions et des alternatives, j'utilise des curseurs. Il n’ya aucun problème à obtenir les données dont j’ai besoin jusqu’à ce que je tente de joindre les deux tables.

 Tbl_question 
 ------------- 
 _Id 
 Question 
 Categoryid 
 Tbl_alternative 
 --------------- 
 _Id 
 Questionid 
 Categoryid 
 Alternative 

Je veux quelque chose comme ce qui suit:

SELECT tbl_question.question, tbl_alternative.alternative where 
categoryid=tbl_alternative.categoryid AND tbl_question._id = 
tbl_alternative.questionid.` 

Ceci est ma tentative:

public Cursor getAlternative(long categoryid) {
            String[] columns = new String[] { KEY_Q_ID, KEY_IMAGE, KEY_QUESTION, KEY_ALT, KEY_QID};
             String whereClause = KEY_CATEGORYID + "=" + categoryid +" AND "+ KEY_Q_ID +"="+ KEY_QID;
             Cursor cursor = mDb.query(true, DBTABLE_QUESTION + " INNER JOIN "+ DBTABLE_ALTERNATIVE, columns, whereClause, null, null, null, null, null);
             if (cursor != null) {
                  cursor.moveToFirst();
             }
             return cursor;

Je trouve cette façon de former des requêtes plus ardue que le SQL ordinaire, mais j'ai eu le conseil de l'utiliser de cette façon car il est moins sujet aux erreurs.

Question

Comment joindre deux tables SQLite dans mon application?

93
kakka47

Vous avez besoin de la méthode rawQuery .

Exemple:

private final String MY_QUERY = "SELECT * FROM table_a a INNER JOIN table_b b ON a.id=b.other_id WHERE b.property_id=?";

db.rawQuery(MY_QUERY, new String[]{String.valueOf(propertyId)});

Utilisation ? des liaisons au lieu de mettre des valeurs dans une requête sql brute.

198
pawelzieba

Une autre méthode consiste à créer une vue qui est ensuite interrogée comme une table. Dans de nombreux gestionnaires de bases de données, l’utilisation d’une vue peut améliorer les performances.

CREATE VIEW xyz SELECT q.question, a.alternative  
   FROM tbl_question AS q, tbl_alternative AS a
  WHERE q.categoryid = a.categoryid 
    AND q._id = a.questionid;

C’est de mémoire, il peut donc y avoir des problèmes de syntaxe. http://www.sqlite.org/lang_createview.html

Je mentionne cette approche car vous pouvez alors utiliser SQLiteQueryBuilder avec la vue car vous avez laissé entendre que cela était préférable.

20
phreed

En plus de la réponse de @ pawelzieba, qui est sans aucun doute correcte, de joindre deux tables, alors que vous pouvez utiliser un INNER JOIN comme ça

SELECT * FROM expense INNER JOIN refuel
ON exp_id = expense_id
WHERE refuel_id = 1

via une requête brute comme celle-ci -

String rawQuery = "SELECT * FROM " + RefuelTable.TABLE_NAME + " INNER JOIN " + ExpenseTable.TABLE_NAME
        + " ON " + RefuelTable.EXP_ID + " = " + ExpenseTable.ID
        + " WHERE " + RefuelTable.ID + " = " +  id;
Cursor c = db.rawQuery(
        rawQuery,
        null
);

en raison de la compatibilité ascendante de SQLite avec la méthode primitive d'interrogation, nous transformons cette commande en ceci -

SELECT *
FROM expense, refuel
WHERE exp_id = expense_id AND refuel_id = 1

et donc être en mesure de tirer parti de la méthode d'assistance SQLiteDatabase.query ()

Cursor c = db.query(
        RefuelTable.TABLE_NAME + " , " + ExpenseTable.TABLE_NAME,
        Utils.concat(RefuelTable.PROJECTION, ExpenseTable.PROJECTION),
        RefuelTable.EXP_ID + " = " + ExpenseTable.ID + " AND " + RefuelTable.ID + " = " +  id,
        null,
        null,
        null,
        null
);

Pour un article de blog détaillé, vérifiez ceci http://blog.championswimmer.in/2015/12/doing-a-table-join-in-Android-without-using-rawquery

12
Arnav Gupta

"Colonne ambiguë" signifie généralement que le même nom de colonne apparaît dans au moins deux tableaux; le moteur de base de données ne peut pas dire lequel vous voulez. Utilisez des noms de table complets ou des alias de table pour supprimer toute ambiguïté.

Voici un exemple que j'ai eu dans mon éditeur. Cela vient du problème de quelqu'un d'autre, mais devrait quand même avoir un sens.

select P.* 
from product_has_image P
inner join highest_priority_images H 
        on (H.id_product = P.id_product and H.priority = p.priority)