【问题标题】:SQLite : How to populate a boolean field on a pojo, from a subQuerySQLite:如何从 subQuery 填充 pojo 上的布尔字段
【发布时间】:2018-12-13 07:41:05
【问题描述】:

我想返回一个类似的帖子列表。

@Query("SELECT * FROM posts")
List<Post> getPosts()

我有一个pojo。

post {
   name:String
   id :String
   postUid:String
   userHasNewContent:Boolean
}

现在,我希望列表中的每个帖子都有userHasNewContent:Boolean,通过检查拥有此帖子的用户是否有新内容(不超过一周)来填充

所以我尝试了。

@Query("SELECT *,
       (SELECT content_uid FROM content WHERE content_uid = postUid AND
        contentTime < :aWeekAgo)AS userHasNewContent 
      FROM posts")
List<Post> getPosts(String aWeekAgo)

内容在哪里: 内容{ contentTime:Long //Unix时间戳 标识:字符串 }

public static Long aWeekAgo() {
        long day = (1000 * 60) * 60 * 24;
        return System.currentTimeMillis() - day * 7;
    }

这似乎没有按预期工作,我是这样做的吗?

编辑 好的,写完问题后,现在很清楚我想做什么。这是简短的版本。

//Get all posts
@Query("SELECT * FROM posts")
List<Post> getPosts()

//Then loop through them.
@Query("SELECT count(*) FROM content WHERE contentId :contentUID AND soundTime < : aWeekAgo")
int checkIfUserHasNewContent(String uid, long aWeekAgo);


List<Post> postsWithNewContentIndicator = new ArrayList<>();
for (Post post : postsFromDb) {
    post.userHasNewContent(checkIfUserHasNewContent(post.getUid()) > 0);
    postsWithNewContentIndicator.add(post);
}

所以,但我想通过单个查询来执行此操作,而不是使用此循环。

【问题讨论】:

  • 你用什么格式存储你的时间?它与aWeekAgo 使用的格式完全相同吗?它是一种可以有意义地比较不平等的格式吗?
  • 哦,这是unix时间戳,在long,所以aWeekAgo是`System.currentTimeMillis() - ((1000 * 60) * 60 * 24 * 7)`
  • 酷。您经常看到人们试图使用MM-DD-YYYY 之类的东西,但它根本无法正常工作。 Unix 时间通常以秒为单位,而不是毫秒,但只要它始终如一……
  • @Shawn 是的,你觉得我应该怎么做?
  • SQLite 使用整数而不是布尔值。因此,如果您得到 True 或 False,请将传入的数据分别转换为 1 和 0。

标签: java android sql sqlite android-room


【解决方案1】:

您需要将查询重写为以下内容

SELECT 
  *, 
  (
    (
      SELECT 
        COUNT(*) 
      FROM 
        (
          SELECT 
            content_uid 
          FROM 
            content 
          WHERE 
            content_uid = postUid 
            AND contentTime > : aWeekAgo
        )
    )> 0
  ) AS userHasNewContent 
FROM 
  posts

【讨论】:

  • 好的,这样做了,但是时间有问题,似乎忽略了它并且即使用户有超过一周的内容也会返回 true。我也将代码更改为。 "SELECT *, " + "(SELECT COUNT(content_uid) FROM content WHERE content_uid = uid AND content_time &lt; :aWeekAgo)&gt; 0 " + "AS userHasNewContent " + "FROM posts ORDER by time DESC"
  • @Relm 我认为这是唯一的问题,所有其他部分都很好。你能指定 contentTime 和 aWeekAgo 实际上是什么吗?他们的数据类型和一组样本值?如果它们是时间戳,我认为你需要一个 > 而不是
【解决方案2】:

假设帖子和用户是一对一的,你可以通过加入来做到这一点。

SELECT posts.name, posts.uid, posts.postUid, 
  (content.contentTime < :aWeekAgo) as userHasNewContent
FROM posts inner join content on content.uid = post.uid

如果用户到帖子是 1 到 n,您将需要使用 group 和 have too。

【讨论】:

    【解决方案3】:

    你的子查询应该写成case:

    SELECT CASE WHEN EXISTS (
       SELECT content_uid FROM content WHERE content_uid = postUid AND
           contentTime < :aWeekAgo
    )
    THEN CAST(1 AS BIT)
    ELSE CAST(0 AS BIT) END
    

    【讨论】:

    • Sqlite 没有“BIT”类型。
    猜你喜欢
    • 2018-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多