sqlLiteDatabase.query() 用于内部连接
sqlLiteDatabase.query() for 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
您将无法将查询与联接一起使用,而是将 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);
您有 2 个选择:
- 使用
rawQuery
方法
- 从 SELECT 语句创建视图并在其上使用
query
方法
编辑:
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 class 的 onCreate 方法中的此语句 - 即您定义数据库的方法 tables。之后,您可以使用 "my_view",就好像它是具有 2 列("name" 和 "distance")的 table。
不过我不建议使用这种方法 - 它可能会使您的数据库变得有点混乱,而且我不确定它对性能有何影响!
编辑 2:
搞砸 rawQuery 和视图语句 - 似乎是更好的解决方案。
您可以将联接放在 table
变量中。
String table = "tblLocal local " +
"inner join tblPlaces place " +
"on place._id = local._id";
有关示例,请参阅 Google 的 IOSched 应用程序。看看 provider package and the SelectionBuilder class.
A SQLiteQueryBuilder
用于构造查询字符串,它所做的只是将 table 变量连接到查询的其余部分。参见 https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/database/sqlite/SQLiteQueryBuilder.java#201
我只是想添加一个示例,其中包含来自实际应用程序的代码,但我的解决方案与@rubenlop88 基本相同,即在 table 变量中进行连接。我和您一样,不想使用 rawquery
,因为我希望能够使用 SQLiteQueryBuilder
在内容提供程序中包含选择和投影参数。我记得当时获取编写此代码所需的信息对我来说非常困难,所以我 post 希望它能帮助其他人。
在我的 app/database 中,我有两个 table。一个包含信号列表。另一个包含事件列表,其中每个事件(即打开或关闭)对应于特定信号。我的 tables 之一是一个简单的连接,它将所有事件与其特定信号合并。另一个 table 是一个更复杂的连接示例,它允许我查询所有信号的当前状态。
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;
}
以下是在查询中使用 JOIN
的两种方法
TABLE1
,TABLE2
are table names and TABLE1.THREAD_ID
,TABLE2.KEY_TREAD_ID
are column names
1.Using.rawQuery()
String rawQuery = "SELECT * FROM " +TABLE1 + " INNER JOIN " + TABLE2
+ " ON " + TABLE1 .THREAD_ID + " = " + TABLE2.KEY_TREAD_ID;
return db.rawQuery(rawQuery,null);
2.Using .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;
Projection and .query()
String[] projectio = new String[]{
TABLE1 + "." + TABLE1.KEY_PARENT,
TABLE2 + "." + TABLE2 .KEY_STUDENT}
return queryBuilder.query(db, projectio, null, null, null,
null, null);
我想从 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
您将无法将查询与联接一起使用,而是将 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);
您有 2 个选择:
- 使用
rawQuery
方法 - 从 SELECT 语句创建视图并在其上使用
query
方法
编辑:
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 class 的 onCreate 方法中的此语句 - 即您定义数据库的方法 tables。之后,您可以使用 "my_view",就好像它是具有 2 列("name" 和 "distance")的 table。
不过我不建议使用这种方法 - 它可能会使您的数据库变得有点混乱,而且我不确定它对性能有何影响!
编辑 2:
搞砸 rawQuery 和视图语句 -
您可以将联接放在 table
变量中。
String table = "tblLocal local " +
"inner join tblPlaces place " +
"on place._id = local._id";
有关示例,请参阅 Google 的 IOSched 应用程序。看看 provider package and the SelectionBuilder class.
A SQLiteQueryBuilder
用于构造查询字符串,它所做的只是将 table 变量连接到查询的其余部分。参见 https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/database/sqlite/SQLiteQueryBuilder.java#201
我只是想添加一个示例,其中包含来自实际应用程序的代码,但我的解决方案与@rubenlop88 基本相同,即在 table 变量中进行连接。我和您一样,不想使用 rawquery
,因为我希望能够使用 SQLiteQueryBuilder
在内容提供程序中包含选择和投影参数。我记得当时获取编写此代码所需的信息对我来说非常困难,所以我 post 希望它能帮助其他人。
在我的 app/database 中,我有两个 table。一个包含信号列表。另一个包含事件列表,其中每个事件(即打开或关闭)对应于特定信号。我的 tables 之一是一个简单的连接,它将所有事件与其特定信号合并。另一个 table 是一个更复杂的连接示例,它允许我查询所有信号的当前状态。
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;
}
以下是在查询中使用 JOIN
的两种方法
TABLE1
,TABLE2
are table names andTABLE1.THREAD_ID
,TABLE2.KEY_TREAD_ID
are column names
1.Using.rawQuery()
String rawQuery = "SELECT * FROM " +TABLE1 + " INNER JOIN " + TABLE2
+ " ON " + TABLE1 .THREAD_ID + " = " + TABLE2.KEY_TREAD_ID;
return db.rawQuery(rawQuery,null);
2.Using .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;
Projection and .query()
String[] projectio = new String[]{
TABLE1 + "." + TABLE1.KEY_PARENT,
TABLE2 + "." + TABLE2 .KEY_STUDENT}
return queryBuilder.query(db, projectio, null, null, null,
null, null);