我已经阅读了文章
代码A在Android Studio中运行良好
目前希望先按
starred desc
排序,再按createdDate desc
排序,所以我把Code A换成Code B。
代码B可以编译运行,但是我得到错误结果,所有情况都指向“
Case WHEN :sortBy = 'TEXT_ASC' THEN text END asc"
.
顺便说一句,代码C和代码D无法编译。
代码A
@Query("SELECT * FROM info_table ORDER BY " +
"CASE WHEN :sortBy = 'START_PRIORITY' THEN starred END desc, " +
"Case WHEN :sortBy = 'TEXT_DESC' THEN text END desc, "+
"Case WHEN :sortBy = 'TEXT_ASC' THEN text END asc"
)
代码 B
@Query("SELECT * FROM info_table ORDER BY " +
"CASE WHEN :sortBy = 'START_PRIORITY' THEN starred END desc, createdDate desc," +
"Case WHEN :sortBy = 'TEXT_DESC' THEN text END desc, "+
"Case WHEN :sortBy = 'TEXT_ASC' THEN text END asc"
)
代码C
@Query("SELECT * FROM info_table ORDER BY " +
"CASE WHEN :sortBy = 'START_PRIORITY' THEN starred ,createdDate END desc, " +
"Case WHEN :sortBy = 'TEXT_DESC' THEN text END desc, "+
"Case WHEN :sortBy = 'TEXT_ASC' THEN text END asc"
)
代码 D
@Query("SELECT * FROM info_table ORDER BY " +
"CASE WHEN :sortBy = 'START_PRIORITY' THEN starred END desc, THEN createdDate END desc," +
"Case WHEN :sortBy = 'TEXT_DESC' THEN text END desc, "+
"Case WHEN :sortBy = 'TEXT_ASC' THEN text END asc"
)
我不相信你想要的是使用
CASE WHEN THEN ELSE END
构造是可行的,因为它们只能在表达式可接受的地方使用。
CASE WHEN THEN ELSE END
结构是可行的。然而,使用 CTE 可能更容易理解。但是,根据问题中的链接,您似乎考虑了其他选项,这是不可接受的,那么第 4 种方法可能是利用公用表表达式(CTE's)和/或子查询(前者通常更简单).
此方法可能涉及 3 个基础查询 (CTE),其中只有 1 个将根据
WHERE
子句返回任何行,相应地 SELECT
s 和 ORDER
s。最终输出是使用 UNION
s 组合的 3 个查询。
使用 SQLite 工具 (Navicat) 考虑这个示例/演示,注意它演示了所有 3 种排列:-
/* Cleanup Testing Environment (just in case) */
DROP TABLE IF EXISTS info_table;
/* Create the table and then load some testing data */
CREATE TABLE IF NOT EXISTS info_table (id INTEGER PRIMARY KEY, `text` TEXT, createdDate TEXT, starred TEXT);
INSERT INTO info_table (createdDate, starred, `text`) VALUES
('2023-01-01','starred001','ZZZZ')
,('2023-01-01','starred006','AAAA')
,('2022-01-01','starred009','YYYY')
,('2022-02-01','starred008','XXXX')
,('2022-03-01','starred007','WWWW')
;
/* First run */
WITH
/* optional but allows testing outside of room in sqlite tool*/
cte1(sortBy) AS (SELECT 'START_PRIORITY' /*'TEXT_DESC'*/ /*'TEXT_ASC'*/),
/* only 1 of the following will select any rows due to the WHERE clause*/
cte2 AS (SELECT * FROM info_table WHERE (SELECT sortBy FROM cte1) = 'START_PRIORITY' ORDER BY createddate DESC, starred DESC),
cte3 AS (SELECT * FROM info_table WHERE (SELECT sortBy FROM cte1) = 'TEXT_DESC' ORDER BY `TEXT` DESC),
cte4 AS (SELECT * FROM info_table WHERE (SELECT sortBy FROM cte1) = 'TEXT_ASC' ORDER BY `TEXT` ASC)
/* combine all three outputs 2 of which will return no rows */
SELECT * FROM cte2 UNION ALL SELECT * FROM cte3 UNION ALL SELECT * FROM cte4
;
/* Second run */
WITH
/* optional but allows testing outside of room in sqlite tool*/
cte1(sortBy) AS (SELECT /*'START_PRIORITY'*/ 'TEXT_DESC' /*'TEXT_ASC'*/),
/* only 1 of the following will select any rows due to the WHERE clause*/
cte2 AS (SELECT * FROM info_table WHERE (SELECT sortBy FROM cte1) = 'START_PRIORITY' ORDER BY createddate DESC, starred DESC),
cte3 AS (SELECT * FROM info_table WHERE (SELECT sortBy FROM cte1) = 'TEXT_DESC' ORDER BY `TEXT` DESC),
cte4 AS (SELECT * FROM info_table WHERE (SELECT sortBy FROM cte1) = 'TEXT_ASC' ORDER BY `TEXT` ASC)
/* combine all three outputs 2 of which will return no rows */
SELECT * FROM cte2 UNION ALL SELECT * FROM cte3 UNION ALL SELECT * FROM cte4
;
/* Thrid and final run */
WITH
/* optional but allows testing outside of room in sqlite tool*/
cte1(sortBy) AS (SELECT /*'START_PRIORITY'*/ /*'TEXT_DESC'*/ 'TEXT_ASC'),
/* only 1 of the following will select any rows due to the WHERE clause*/
cte2 AS (SELECT * FROM info_table WHERE (SELECT sortBy FROM cte1) = 'START_PRIORITY' ORDER BY createddate DESC, starred DESC),
cte3 AS (SELECT * FROM info_table WHERE (SELECT sortBy FROM cte1) = 'TEXT_DESC' ORDER BY `TEXT` DESC),
cte4 AS (SELECT * FROM info_table WHERE (SELECT sortBy FROM cte1) = 'TEXT_ASC' ORDER BY `TEXT` ASC)
/* combine all three outputs 2 of which will return no rows */
SELECT * FROM cte2 UNION ALL SELECT * FROM cte3 UNION ALL SELECT * FROM cte4
;
/* Cleanup Testing Environment */
DROP TABLE IF EXISTS info_table;
结果(根据运行顺序):-
然后将其中一个运行放到
@Query
的 SQL 中并对其进行定制以传递变量是一件简单的事情:-
例如:-
@Query("WITH " +
"/* optional but allows testing outside of room in sqlite tool*/" +
"cte1(sortBy) AS (SELECT :sortBy)," + /* <<<<<<<<<< passed valued */
" /* only 1 of the following will select any rows due to the WHERE clause*/" +
"cte2 AS (SELECT * FROM info_table WHERE (SELECT sortBy FROM cte1) = 'START_PRIORITY' ORDER BY createddate DESC, starred DESC)," +
"cte3 AS (SELECT * FROM info_table WHERE (SELECT sortBy FROM cte1) = 'TEXT_DESC' ORDER BY `TEXT` DESC)," +
"cte4 AS (SELECT * FROM info_table WHERE (SELECT sortBy FROM cte1) = 'TEXT_ASC' ORDER BY `TEXT` ASC)" +
" /* combine all three outputs 2 of which will return no rows */" +
"SELECT * FROM cte2 UNION ALL SELECT * FROM cte3 UNION ALL SELECT * FROM cte4" +
";")
fun getSortedViaCTEs(sortBy: String): List<InfoTable>
为了实际证明这一点,与 B、C 和 D 相比,请考虑以下活动代码:-
db = TheDatabase.getInstance(这个) dao = db.getAllDAOs()
dao.deleteAllInfoTableRows()
dao.insert(InfoTable(createdDate = "2023-01-01", starred = "starred001", text = "ZZZZ"))
dao.insert(InfoTable(createdDate = "2022-01-01", starred = "starred009", text = "YYYY"))
dao.insert(InfoTable(createdDate = "2022-02-01", starred = "starred008", text = "XXXX"))
dao.insert(InfoTable(createdDate = "2022-03-01", starred = "starred007", text = "WWWW"))
logInfo("SP",dao.getSorted("START_PRIORITY"))
logInfo("TD",dao.getSorted("TEXT_DESC"))
logInfo("TA",dao.getSorted("TEXT_ASC"))
logInfo("V2SP",dao.getSortedViaCTEs("START_PRIORITY"))
logInfo("V2TD",dao.getSortedViaCTEs("TEXT_DESC"))
logInfo("V2TA",dao.getSortedViaCTEs("TEXT_ASC"))
与
logInfo
是:-
fun logInfo(tagSuffix: String, infoTableExtract: List<InfoTable>) {
for (i in infoTableExtract) {
Log.d("DBINFO_$tagSuffix","ID = ${i.id} CreatedDate = ${i.createdDate} Starred = ${i.starred} Text = ${i.text}")
}
}
结果
来自您的代码:-
2023-05-19 11:24:50.626 D/DBINFO_SP: ID = 2 CreatedDate = 2022-01-01 Starred = starred009 Text = YYYY
2023-05-19 11:24:50.626 D/DBINFO_SP: ID = 3 CreatedDate = 2022-02-01 Starred = starred008 Text = XXXX
2023-05-19 11:24:50.626 D/DBINFO_SP: ID = 4 CreatedDate = 2022-03-01 Starred = starred007 Text = WWWW
2023-05-19 11:24:50.626 D/DBINFO_SP: ID = 1 CreatedDate = 2023-01-01 Starred = starred001 Text = ZZZZ
2023-05-19 11:24:50.628 D/DBINFO_TD: ID = 1 CreatedDate = 2023-01-01 Starred = starred001 Text = ZZZZ
2023-05-19 11:24:50.628 D/DBINFO_TD: ID = 4 CreatedDate = 2022-03-01 Starred = starred007 Text = WWWW
2023-05-19 11:24:50.628 D/DBINFO_TD: ID = 3 CreatedDate = 2022-02-01 Starred = starred008 Text = XXXX
2023-05-19 11:24:50.628 D/DBINFO_TD: ID = 2 CreatedDate = 2022-01-01 Starred = starred009 Text = YYYY
2023-05-19 11:24:50.629 D/DBINFO_TA: ID = 1 CreatedDate = 2023-01-01 Starred = starred001 Text = ZZZZ
2023-05-19 11:24:50.629 D/DBINFO_TA: ID = 4 CreatedDate = 2022-03-01 Starred = starred007 Text = WWWW
2023-05-19 11:24:50.629 D/DBINFO_TA: ID = 3 CreatedDate = 2022-02-01 Starred = starred008 Text = XXXX
2023-05-19 11:24:50.629 D/DBINFO_TA: ID = 2 CreatedDate = 2022-01-01 Starred = starred009 Text = YYYY
来自 CTE 驱动的查询:-
2023-05-19 11:24:50.632 D/DBINFO_V2SP: ID = 1 CreatedDate = 2023-01-01 Starred = starred001 Text = ZZZZ
2023-05-19 11:24:50.632 D/DBINFO_V2SP: ID = 4 CreatedDate = 2022-03-01 Starred = starred007 Text = WWWW
2023-05-19 11:24:50.632 D/DBINFO_V2SP: ID = 3 CreatedDate = 2022-02-01 Starred = starred008 Text = XXXX
2023-05-19 11:24:50.632 D/DBINFO_V2SP: ID = 2 CreatedDate = 2022-01-01 Starred = starred009 Text = YYYY
2023-05-19 11:24:50.636 D/DBINFO_V2TD: ID = 1 CreatedDate = 2023-01-01 Starred = starred001 Text = ZZZZ
2023-05-19 11:24:50.637 D/DBINFO_V2TD: ID = 2 CreatedDate = 2022-01-01 Starred = starred009 Text = YYYY
2023-05-19 11:24:50.637 D/DBINFO_V2TD: ID = 3 CreatedDate = 2022-02-01 Starred = starred008 Text = XXXX
2023-05-19 11:24:50.637 D/DBINFO_V2TD: ID = 4 CreatedDate = 2022-03-01 Starred = starred007 Text = WWWW
2023-05-19 11:24:50.639 D/DBINFO_V2TA: ID = 4 CreatedDate = 2022-03-01 Starred = starred007 Text = WWWW
2023-05-19 11:24:50.640 D/DBINFO_V2TA: ID = 3 CreatedDate = 2022-02-01 Starred = starred008 Text = XXXX
2023-05-19 11:24:50.640 D/DBINFO_V2TA: ID = 2 CreatedDate = 2022-01-01 Starred = starred009 Text = YYYY
2023-05-19 11:24:50.640 D/DBINFO_V2TA: ID = 1 CreatedDate = 2023-01-01 Starred = starred001 Text = ZZZZ
额外的
思考问题后,对
CASE WHEN THEN ELSE END
构造物进行排序,重新排序可以达到预期的效果。
需要考虑的是,END后面的内容都包含在内。因此,当第一个构造不匹配时,您将得到类似的东西:-
ORDER BY DESC, createdDate DESC, TEXT DESC, ASC
或
ORDER BY DESC, createdDate DESC, DESC, TEXT ASC
因此最高优先级排序将是
createdDate DESC
因此 TEXT 列是次要排序因此可能无用。
注意到没有解析的表达式基本上是相同的值,因此排序不受影响。
现在如果你有:-
@Query("SELECT * FROM info_table ORDER BY " +
"CASE WHEN :sortBy = 'TEXT_DESC' THEN text END desc,"+
"CASE WHEN :sortBy = 'TEXT_ASC' THEN text END asc," +
"CASE WHEN :sortBy = 'START_PRIORITY' THEN starred END desc, createdDate desc"
)
fun getSortedV2(sortBy: String): List<InfoTable>
然后
createdDate
将始终是次要排序顺序。所以使用:-
logInfo("SP",dao.getSortedV2("START_PRIORITY"))
logInfo("TD",dao.getSortedV2("TEXT_DESC"))
logInfo("TA",dao.getSortedV2("TEXT_ASC"))
将导致:-
2023-05-19 12:00:38.386 D/DBINFO_SP: ID = 2 CreatedDate = 2022-01-01 Starred = starred009 Text = YYYY
2023-05-19 12:00:38.386 D/DBINFO_SP: ID = 3 CreatedDate = 2022-02-01 Starred = starred008 Text = XXXX
2023-05-19 12:00:38.386 D/DBINFO_SP: ID = 4 CreatedDate = 2022-03-01 Starred = starred007 Text = WWWW
2023-05-19 12:00:38.386 D/DBINFO_SP: ID = 1 CreatedDate = 2023-01-01 Starred = starred001 Text = ZZZZ
2023-05-19 12:00:38.389 D/DBINFO_TD: ID = 1 CreatedDate = 2023-01-01 Starred = starred001 Text = ZZZZ
2023-05-19 12:00:38.389 D/DBINFO_TD: ID = 2 CreatedDate = 2022-01-01 Starred = starred009 Text = YYYY
2023-05-19 12:00:38.390 D/DBINFO_TD: ID = 3 CreatedDate = 2022-02-01 Starred = starred008 Text = XXXX
2023-05-19 12:00:38.390 D/DBINFO_TD: ID = 4 CreatedDate = 2022-03-01 Starred = starred007 Text = WWWW
2023-05-19 12:00:38.393 D/DBINFO_TA: ID = 4 CreatedDate = 2022-03-01 Starred = starred007 Text = WWWW
2023-05-19 12:00:38.393 D/DBINFO_TA: ID = 3 CreatedDate = 2022-02-01 Starred = starred008 Text = XXXX
2023-05-19 12:00:38.393 D/DBINFO_TA: ID = 2 CreatedDate = 2022-01-01 Starred = starred009 Text = YYYY
2023-05-19 12:00:38.393 D/DBINFO_TA: ID = 1 CreatedDate = 2023-01-01 Starred = starred001 Text = ZZZZ
即订单现在看来是正确的。