Select 基于多个标签的 SQLite 数据库中的多个数据
Select multiple data from SQLite database based on multiple tags
我有一个带有一些待办事项列表的 SQLite 数据库。
每一个to do list,都有一个tag栏。
这是我的 SQLite 数据库的示例布局
假设我想 select 带有包含“我”和“妈妈”标签的待办事项列表(即“购买杂货”、“学习”和“假期旅行”),我该怎么做这个?
我考虑过这个,但我认为它行不通。
public getToDoLists (String [] tags) {
this.db = openHelper.getReadableDatabase();
String query = " SELECT * FROM "
+ TABLE_NAME
+ " WHERE "
+ COL2 + " ='" + tags + "'";
c = db.rawQuery(query, null);
.......
.......
}
您可以为此使用正则表达式。
注意,默认不提供正则表达式功能,https://sqlite.org/lang_expr.html#regexp:
No regexp() user function is defined by default and so use of the
REGEXP operator will normally result in an error message. If an
application-defined SQL function named "regexp" is added at run-time,
then the "X REGEXP Y" operator will be implemented as a call to
"regexp(Y,X)".
您可以使用 ICU 扩展加载正则表达式函数:https://sqlite.org/src/artifact?ci=trunk&filename=ext/icu/README.txt。有了那个:
select
"To do list"
from table
where 1==1
and ( "Tags" regexp '.*\bMom\b.*'
or "Tags" regexp '.*\bMe\b.*' )
ICU 正则表达式语法参考:https://unicode-org.github.io/icu/userguide/strings/regexp.html#regular-expression-metacharacters
这不是一个简单的查询。
您将搜索的标签作为字符串数组传递。
一种选择是使用 for
循环,它将迭代数组的所有标签,并为每个标签 运行 查询,但这对性能不利。
我建议的选项是将所有用 ,
分隔的标签连接到一个字符串中,并将其传递给查询,查询又会使用递归 CTE 和 运行 SELECT...
语句和 EXISTS...
来获取匹配的行:
public Cursor getToDoLists(String[] tags) {
String joinedTags = TextUtils.join(",", tags);
String query =
"WITH " +
" list(tag) AS (SELECT ?), " +
" cte(tag, value) AS ( " +
" SELECT SUBSTR(tag, 1, INSTR(tag || ',', ',') - 1), " +
" SUBSTR(tag, INSTR(tag || ',', ',') + 1) " +
" FROM list " +
" UNION ALL " +
" SELECT SUBSTR(value, 1, INSTR(value || ',', ',') - 1), " +
" SUBSTR(value, INSTR(value || ',', ',') + 1) " +
" FROM cte " +
" WHERE LENGTH(value) > 0 " +
") " +
"SELECT t.* " +
"FROM " + TABLE_NAME + " t " +
"WHERE EXISTS ( " +
" SELECT 1 FROM cte c " +
" WHERE ',' || REPLACE(t.Tags, ', ', ',') || ',' LIKE '%,' || c.tag || ',%' " +
")";
SQLiteDatabase db = this.getReadableDatabase();
return db.rawQuery(query, new String[] {joinedTags});
}
我在 sql 语句中使用 REPLACE(t.Tags, ', ', ',')
因为我看到 Tags
列中的标签分隔符是 ', '
而不是 ','
.
如果我弄错了,请将 REPLACE(t.Tags, ', ', ',')
更改为 t.Tags
.
方法 getToDoLists()
必须放在您的 SQLiteOpenHelper
class 中,您可以从 activity class 中调用它,例如:
Cursor c = openHelper.getToDoLists(new String[] {"Me", "Mom"});
它 returns 一个 Cursor
的行符合您的条件,您可以对其进行迭代。
要使用 TextUtils.join()
,您需要导入:
import android.text.TextUtils;
查看 demo SQLite 中的工作原理。
我有一个带有一些待办事项列表的 SQLite 数据库。 每一个to do list,都有一个tag栏。
这是我的 SQLite 数据库的示例布局
假设我想 select 带有包含“我”和“妈妈”标签的待办事项列表(即“购买杂货”、“学习”和“假期旅行”),我该怎么做这个?
我考虑过这个,但我认为它行不通。
public getToDoLists (String [] tags) {
this.db = openHelper.getReadableDatabase();
String query = " SELECT * FROM "
+ TABLE_NAME
+ " WHERE "
+ COL2 + " ='" + tags + "'";
c = db.rawQuery(query, null);
.......
.......
}
您可以为此使用正则表达式。
注意,默认不提供正则表达式功能,https://sqlite.org/lang_expr.html#regexp:
No regexp() user function is defined by default and so use of the REGEXP operator will normally result in an error message. If an application-defined SQL function named "regexp" is added at run-time, then the "X REGEXP Y" operator will be implemented as a call to "regexp(Y,X)".
您可以使用 ICU 扩展加载正则表达式函数:https://sqlite.org/src/artifact?ci=trunk&filename=ext/icu/README.txt。有了那个:
select
"To do list"
from table
where 1==1
and ( "Tags" regexp '.*\bMom\b.*'
or "Tags" regexp '.*\bMe\b.*' )
ICU 正则表达式语法参考:https://unicode-org.github.io/icu/userguide/strings/regexp.html#regular-expression-metacharacters
这不是一个简单的查询。
您将搜索的标签作为字符串数组传递。
一种选择是使用 for
循环,它将迭代数组的所有标签,并为每个标签 运行 查询,但这对性能不利。
我建议的选项是将所有用 ,
分隔的标签连接到一个字符串中,并将其传递给查询,查询又会使用递归 CTE 和 运行 SELECT...
语句和 EXISTS...
来获取匹配的行:
public Cursor getToDoLists(String[] tags) {
String joinedTags = TextUtils.join(",", tags);
String query =
"WITH " +
" list(tag) AS (SELECT ?), " +
" cte(tag, value) AS ( " +
" SELECT SUBSTR(tag, 1, INSTR(tag || ',', ',') - 1), " +
" SUBSTR(tag, INSTR(tag || ',', ',') + 1) " +
" FROM list " +
" UNION ALL " +
" SELECT SUBSTR(value, 1, INSTR(value || ',', ',') - 1), " +
" SUBSTR(value, INSTR(value || ',', ',') + 1) " +
" FROM cte " +
" WHERE LENGTH(value) > 0 " +
") " +
"SELECT t.* " +
"FROM " + TABLE_NAME + " t " +
"WHERE EXISTS ( " +
" SELECT 1 FROM cte c " +
" WHERE ',' || REPLACE(t.Tags, ', ', ',') || ',' LIKE '%,' || c.tag || ',%' " +
")";
SQLiteDatabase db = this.getReadableDatabase();
return db.rawQuery(query, new String[] {joinedTags});
}
我在 sql 语句中使用 REPLACE(t.Tags, ', ', ',')
因为我看到 Tags
列中的标签分隔符是 ', '
而不是 ','
.
如果我弄错了,请将 REPLACE(t.Tags, ', ', ',')
更改为 t.Tags
.
方法 getToDoLists()
必须放在您的 SQLiteOpenHelper
class 中,您可以从 activity class 中调用它,例如:
Cursor c = openHelper.getToDoLists(new String[] {"Me", "Mom"});
它 returns 一个 Cursor
的行符合您的条件,您可以对其进行迭代。
要使用 TextUtils.join()
,您需要导入:
import android.text.TextUtils;
查看 demo SQLite 中的工作原理。