INNER JOIN的sqlLiteDatabase.query()

时间:2015-07-22 15:28:15

标签: android android-sqlite inner-join

我想从Android SQLite数据库中执行以下查询:

select place.permit_name, local.local_distance
from tblLocal local
inner join tblPlaces place
on place._id = local._id
order by local.local_distance asc

我尝试使用query()而不是rawQuery()。 我不知道如何指定INNER JOIN / ON。 我该怎么做?

final String table = PlacesDataContract.PlacesDataEntry.TABLE_NAME;
final String[] columns =  { PlacesDataContract.PlacesDataEntry.COLUMN_NAME_PERMIT_NAME. , LocalDataContract.LocalDataEntry.COLUMN_NAME_LOCAL_DISTANCE};
final String orderBy = LocalDataContract.LocalDataEntry.COLUMN_NAME_LOCAL_DISTANCE + " ASC"; 

Cursor cursor = sqLiteDatabase.query(table, // table
        columns, // columns
        null, // selection
        null, // selectionArgs
        null, // groupBy
        null, // having
        orderBy, // orderBy
        null); // limit

5 个答案:

答案 0 :(得分:3)

您可以将联接放在table变量中。

String table = "tblLocal local " +
    "inner join tblPlaces place " +
    "on place._id = local._id";

有关示例,请参阅Google的IOSched应​​用。请查看provider包和SelectionBuilder类。

SQLiteQueryBuilder用于构造查询字符串,它所做的只是将表变量连接到查询的其余部分。见https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/database/sqlite/SQLiteQueryBuilder.java#201

答案 1 :(得分:2)

您有两个选择:

  1. 使用rawQuery方法
  2. 从SELECT语句创建视图并在其上使用query方法
  3. 编辑:

    SQLite支持视图 - 您可以查看文档here。 通常你可以运行这样的语句:

    CREATE VIEW my_view AS
    SELECT place.permit_name as name, local.local_distance as distance
    FROM tblLocal local
    INNER JOIN tblPlaces place
    ON place._id = local._id
    ORDER BY local.local_distance ASC
    

    您应该在SQLite Helper类的onCreate方法中运行此语句 - 即您定义数据库表的方法。之后,您可以使用" my_view"好像它是一个有2列的表("名称"和"距离")。

    我不建议使用这种方法 - 它可能会使您的数据库变得更加混乱,而且我不确定它会如何影响性能!

    编辑2:

    调整rawQuery和view语句 - this似乎是一个更好的解决方案。

答案 2 :(得分:1)

您无法对连接使用查询,而是将rawquery与连接一起使用

    String sql = "select place.permit_name, local.local_distance\n" +
                 "from tblLocal local\n" +
                 "inner join tblPlaces place\n" +
                 "on place._id = local._id\n" +
                 "order by local.local_distance asc";

    Cursor cursor = sqLiteDatabase.rawQuery(sql, null);

答案 3 :(得分:1)

我只想添加一个包含实际应用程序代码的示例,但我的解决方案基本上与@ rubenlop88相同,后者是在表变量中进行连接。我和你一样,不想使用rawquery,因为我希望能够使用SQLiteQueryBuilder在内容提供商中包含选择和投影参数。我记得当时获取编写此代码所需的信息对我来说非常困难所以我发布它希望它能帮助其他人。

在我的app /数据库中,我有两个表。一个包含信号列表。另一个包含事件列表,其中每个事件(即,开启或关闭)对应于特定信号。我的一个是一个简单的连接,它将所有事件与其特定信号合并。另一个是一个更复杂的连接示例,它允许我查询所有信号的当前状态。

private static final String TABLE_JOINED_EVENTS_SIGNALS = DataContract.LinEventEntry.TABLE_NAME + " INNER JOIN " +
        DataContract.LinSignalTable.TABLE_NAME + " ON " +
        DataContract.LinSignalTable._ID + "=" + DataContract.LinEventEntry.COLUMN_NAME_SIGNAL_ID;

/**
 * Using this constant as a parameter for
 * {@link android.database.sqlite.SQLiteQueryBuilder#setTables(String)} will create a query
 * that gets the highest id (most recent) row for each unique signal name
 */
private static final String TABLE_MAX_ID_GROUP_BY_SIGNAL =
        "(SELECT max(" + DataContract.LinEventEntry._ID + ") as max_id " +
                "FROM " + DataContract.LinEventEntry.TABLE_NAME +
                " GROUP BY " + DataContract.LinEventEntry.COLUMN_NAME_SIGNAL_ID + ") " +
                "as t1 INNER JOIN " + DataContract.LinEventEntry.TABLE_NAME +
                " as t2 on t1.max_id=t2." + DataContract.LinEventEntry._ID +
                " INNER JOIN " + DataContract.LinSignalTable.TABLE_NAME + " ON " +
                DataContract.LinSignalTable._ID + "=" + DataContract.LinEventEntry.COLUMN_NAME_SIGNAL_ID;

public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    if (sortOrder == null || sortOrder.isEmpty()) {
        sortOrder = DEFAULT_EVENT_SORT_ORDER;
    }
    SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
    queryBuilder.setTables(TABLE_JOINED_EVENTS_SIGNALS);

    switch (sURIMatcher.match(uri)) {
        case EVENTS:
            break;
        case SIGNAL_NAME:
            queryBuilder.appendWhere(DataContract.COLUMN_NAME_SIGNAL_NAME +
                    "='" + uri.getLastPathSegment() + "'");
            break;
        case EVENT_ID:
            queryBuilder.appendWhere(
                    DataContract.LinEventEntry._ID + "=" + uri.getLastPathSegment());
            break;
        case EVENTS_BY_SIGNAL:
            queryBuilder.setTables(TABLE_MAX_ID_GROUP_BY_SIGNAL);
            break;
        default:
            throw new IllegalArgumentException("Unsupported URI: " + uri);
    }

    SQLiteDatabase db = mSqlHelper.getReadableDatabase();

    Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null,
            sortOrder, MAX_EVENTS_TO_RETURN);

    cursor.setNotificationUri(getContext().getContentResolver(), uri);
    return cursor;
}

答案 4 :(得分:1)

以下是在查询中使用JOIN的两种方法

  

TABLE1TABLE2是表名,TABLE1.THREAD_IDTABLE2.KEY_TREAD_ID是列名

1。使用.rawQuery()

String rawQuery = "SELECT * FROM " +TABLE1 + " INNER JOIN " + TABLE2
                    + " ON " + TABLE1 .THREAD_ID + " = " + TABLE2.KEY_TREAD_ID;

return db.rawQuery(rawQuery,null);

2。使用.query()

SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();

SQLiteDatabase db = dbHelper.getWritableDatabase();
               db.enableWriteAheadLogging();

 String tableName =TABLE1  + " INNER JOIN " + TABLE2 + " ON " +  TABLE1+ "." +TABLE1.THREAD_ID + " = " + TABLE2+ "." +TABLE2.KEY_TREAD_ID;
  

投影和.query()

 String[] projectio = new String[]{
                    TABLE1 + "." + TABLE1.KEY_PARENT,
                    TABLE2 + "." + TABLE2 .KEY_STUDENT}


 return queryBuilder.query(db, projectio, null, null, null,
                    null, null);