如何从 android 中的房间数据库中的单个查询获取项目列表和列值的总和

How to get list of items and sum of values of a column from a single query in room database in android

我想在我的应用程序中显示日期明智的项目列表。该列表将有一个 header,其中包含日期和列值的总和。

24.12.2021 25
Book1 10
Book2 05
Book3 10

这是实体:

@Entity(tableName = "books")
public class Books {
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "id")
    private int id;

    @ColumnInfo(name = "date")
    @TypeConverters({TimestampConverter.class})
    private long mDate;

    @ColumnInfo(name = "quantity")
    private double mQuantity;

    @ColumnInfo(name = "name")
    private String mName;

我正在尝试使用嵌套的 recyclerview 并创建了一个 Parent class :

public class ParentEntry {
    private double totalBooks;
 
    private long dateToday;

    public  List<Books> books;
}

这是道:

 @Query("SELECT SUM(quantity) as totalBooks, date as dateToday, *  FROM books GROUP BY date ORDER 
  BY date Asc ")
    LiveData<List<ParentEntry>> getAllParentEntries();

但我收到以下错误: 错误:无法弄清楚如何从游标读取此字段。 警告:查询 returns 一些未使用的列 [id, date, quantity, name]。您可以在字段上使用 @ColumnInfo 注释来指定映射。您可以使用 @RewriteQueriesToDropUnusedColumns 注释该方法,以指示 Room 重写您的查询以避免获取未使用的列。 Parent条目中有一些查询未返回的字段 [books]。如果不应该从结果中读取它们,您可以使用 @Ignore 注释标记它们。您可以通过使用 @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH) 注释该方法来抑制此警告。 query:totalBooks、dateToday、id、date、quantity、name 返回的列。 Parent条目中的字段:totalBooks、dateToday、books。 LiveData getAllParentEntries();

如何在单个查询中查询数量列和日期的列表和总和?非常感谢任何帮助。

为了在 POJO 中构建列表,您需要一个@Relation。

所以 ParentEntity 需要类似于:-

class ParentEntry {
    long dateToday;
    double totalBooks;
    @Relation(entity = Books.class,
    parentColumn = "dateToday",
    entityColumn = "date")
    List<Books> booksList;

}

因此您需要一个查询,然后检索列名与成员变量名匹配的非列表值(dateToday 和 totalBooks),这可能是 :-

@Transaction
@Query("SELECT date AS dateToday, total(quantity) AS totalBooks FROM books GROUP BY date ORDER BY date ASC;")
abstract List<ParentEntryV2> getParentEntries();

例如来自一本书 table :-

使用:-

    for(ParentEntryV2 pev2: dao.getParentEntries()) {
        Log.d("PEINFO_V2","Date is " + pev2.dateToday + " TotalBooks is " + pev2.totalBooks + " Number of Books in list is " + pev2.booksList.size());
        for (Books b: pev2.booksList) {
            Log.d("PEINFO_V2","\tBook is " + b.getmName() + " quantity is " + b.getmQuantity());
        }
    }

结果:-

D/PEINFO_V2: Date is 1640124943 TotalBooks is 30.0 Number of Books in list is 3
D/PEINFO_V2:    Book is Book1 quantity is 10.0
D/PEINFO_V2:    Book is Book2 quantity is 10.0
D/PEINFO_V2:    Book is Book3 quantity is 10.0
D/PEINFO_V2: Date is 1640211343 TotalBooks is 30.0 Number of Books in list is 3
D/PEINFO_V2:    Book is Book4 quantity is 10.0
D/PEINFO_V2:    Book is Book5 quantity is 10.0
D/PEINFO_V2:    Book is Book6 quantity is 10.0
D/PEINFO_V2: Date is 1640297743 TotalBooks is 30.0 Number of Books in list is 3
D/PEINFO_V2:    Book is Book7 quantity is 10.0
D/PEINFO_V2:    Book is Book8 quantity is 10.0
D/PEINFO_V2:    Book is Book9 quantity is 10.0

额外

关于日期问题(即您只想要 date/time 中的日期部分)那么您可以使用以下但它需要 2 个查询和一个抽象 class 而不是一个接口和其他在 Dao 的单个事务中调用两个查询的函数。道的存在:-

@Transaction
@Query("SELECT date AS dateToday, total(quantity) AS totalBooks FROM books GROUP BY date(date/:timefactor,'unixepoch') ORDER BY date ASC;")
abstract List<ParentEntryV2> getParentEntries(long timefactor);

@Query("SELECT * FROM books WHERE date(date/:timefactor,'unixepoch')=date(:date/:timefactor,'unixepoch')")
abstract List<Books> getBooksPerDate(long date,long timefactor);

@Transaction
@Query("")
List<ParentEntryV2> getParentEntriesV2() {
    List<ParentEntryV2> parentEntryV2List = getParentEntries(1 /* 1000 if precision to millisecs */);
    for(ParentEntryV2 pe: parentEntryV2List) {
        pe.booksList = getBooksPerDate(pe.dateToday,1 /* 1000 if precision to millisecs */);

    }
    return parentEntryV2List;
}
  • 请注意,timefactor 允许 1 或 1000 用于在精度为 1 秒 (1) 和精度为毫秒 (1000) 之间切换。
  • 虽然第一个查询基本相同,除了 GROUP BY,第二个查询用所需的书目(与日期匹配的书)覆盖书目(完全 date/time 匹配的书)。