按日期范围排序查询,然后按其他条件排序。联盟? CONCATENATE?寻找创意

时间:2015-05-08 22:11:39

标签: android mysql sqlite sorting datetime

在我的Android SQLite数据库中,我有一个日期时间为YYYY-MM-DD HH:MM格式的列。我想要一个查询(或实际上是一个光标),它会给我所有的行,比如说2015年5月。排序是我被卡住的地方。我希望我的结果先按周分解,然后每周按基于其他列的分类。

现在我只是按日期时间列排序,然后是其他列。例如:ORDER BY t.TASKS_DATETIME ASC, s.STATUSES_RANK ASC, t.TASKS_CATEGORY。但基本上每一行都有一个独特的日期时间值(即使我不关心这种情况下的小时和分钟),所以没有其他排序发生,最终结果不是非常用户友好。排序顺序对于用户查看和理解此数据非常重要。

我考虑过为每个星期做一个单独的select语句,然后执行UNION ALL来获取月份数据。但是你不能将ORDER BY子句与UNION一起使用,因为它会对整个联合进行排序,而不仅仅是内部的单个select语句。更不用说,它非常丑陋。

我想也许我可以在Android / Java端做到并连接多个Cursor对象。但我无法找到任何办法。这里有人知道吗?我已经离开Java几年了,从来没有那种与语言密切相关的东西。

我想也许我可以用某种方式使用SQLite日期函数[https://www.sqlite.org/lang_datefunc.html]。也许在我的选择中添加一个具有一周中的新列。然后我可以按新列排序,然后是我想要的其他排序标准。或者可能有一种方法可以将范围(或简化的日期时间)放入ORDER BY子句中。但这正在推动我的SQLite技能的界限。这看起来有可能吗?仅供参考,在Android / Java方面,我将此日期时间字符串转换为GregorianCalendar。

我希望有人比我聪明,能指出我的方向!这些选项似乎都不是很好,我无法想到任何其他选项。

如果我无法弄清楚其他任何内容,我会选择UNION选项。并添加一个" week_of_year"列中的每个select语句用于标识该周,如此处其他联合/排序问题所示。然后排序" week_of_year"列,后面是我的其他排序条件。我已经开始研究这个了。但我休息一下,在这里要求更好的想法,因为我的直觉说必须有更好的方法。但也许不是:)。

作为额外的背景,我认为不相关,但以防万一...

这个可怕的查询正在StickyHeaderList [https://github.com/emilsjolander/StickyListHeaders]中使用,其中周是标题。如果我不按日期时间排序,则标题/周最终会出现故障。有时他们甚至会复制。

我可能会在某些时候编写我自己的替代方案或更改这个StickyHeaderList代码,也许是每周/标题需要一个游标而不是整个月的一个。我可以在Java和SQL中更轻松地处理日期。但是我今天没有足够的资源。我想,最让人头疼的是,多选CAB菜单允许我选择不同的列表。如果你碰巧知道一个简单的解决方法,也许我会这样做,并接受重大的返工,而不是搞清楚这个问题。

更新:有效!

非常感谢@CL给我答案。为了后人和清晰,这里有一些注意事项。

正确答案是:

SELECT ...
FROM ...
ORDER BY strftime('%Y%W', t.TASKS_DATETIME),
     s.STATUSES_RANK,
     t.TASKS_CATEGORY

如上所述,数周是挑剔的事情。我还需要考虑那些在一周中的不同日期开始的周数的用户。注意,SQLite默认是在 Monday (而不是星期日)启动ween。此外,关键字为day而非days,用于计算该偏移量。此外,偏移应该到日期时间的右侧

这让我失望:

 "ORDER BY strftime('%Y %W', t." + TASKS_SCHED_DATETIME + weekOffset + ")," + 
     "s." + STATUSES_RANK + " ASC, " +
     "t." + TASKS_CATEGORY + " DESC "

最终成为:ORDER BY strftime('%Y %W', t.task_sched_datetime, '+5 day' ), s.status_rank ASC, t.tasks_category DESC

weekOffset在一个小帮助函数中定义:

private String calculateWeekOfset() {
    int wkStart = App.getWeekStart();
    int offset = 9 - wkStart; // Calendar.MONDAY == 2
    return ", '+" + Integer.toString(offset)+ " day' ";
}

我认为这就是全部。再次感谢!

1 个答案:

答案 0 :(得分:1)

要从时间戳中提取字段,请使用strftime function。 在这种情况下,您需要一年中的一周,以及年份本身,以使不同年份的日期独特:

SELECT ...
FROM ...
ORDER BY strftime('%Y%W', t.TASKS_DATETIME),
         s.STATUSES_RANK,
         t.TASKS_CATEGORY

如果您不想在星期一开始一周,请添加或减去适当的天数:

... strftime('%Y%W', t.TASKS_DATETIME, '+1 days'), ...