在 Android Studio 中使用 CASE 为带有 Room 的 SQLite 请求参数时,如何添加第二个排序项?

问题描述 投票:0回答:1

我已经阅读了文章

代码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"
)
android android-sqlite android-room
1个回答
0
投票

我不相信你想要的是使用

CASE WHEN THEN ELSE END
构造是可行的,因为它们只能在表达式可接受的地方使用。

但是,根据问题中的链接,您似乎考虑了其他选项,这是不可接受的,那么第 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
  • 显然不是要求的结果,例如TD和TA顺序一样

来自 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

即订单现在看来是正确的。

© www.soinside.com 2019 - 2024. All rights reserved.