【发布时间】:2020-01-13 14:12:16
【问题描述】:
问题概述
我正在开发一个用于提醒用户每周目标的简单应用。假设目标是在一周中的特定日子进行 30 分钟的锻炼。
示例目标:在周一、周三、周五锻炼。
该应用还需要跟踪过去的记录,即用户锻炼的日期。可能只是日期,例如:2019-09-02, 2019-09-05, 2019-09-11 表示用户在这几天做了锻炼,而在其他日子没有锻炼(不需要在“锻炼目标” " 星期几)。
目标会随时间改变。假设今天是 2019-09-11,本周的目标([2019-09-09, 2019-09-15])是周一、周三、周五,但从 2019-08-05 到 2019-09-08是周一、周四(连续几周反复)。
我需要存储这些以周为导向的目标和历史练习数据,并能够检索以下内容:
- 本周(或任何一周,假设我可以计算给定日期的任何一周的开始和结束日期)的目标天数。
- 更大范围内的锻炼历史记录以及该范围内的目标天数(例如,显示用户应该锻炼的时间以及他们上个月实际锻炼的时间)。
问题
如何在 SQL 中最好地存储这些数据。
这有点学术,因为我正在开发一个小型 Android 应用程序,并且数据仅供单个用户使用。所以会有很少的数据,我可以成功地使用任何方法,即使是非常笨拙的方法也足够有效。 不过,我想探索一下这个话题,也许能学到一两件事。
可能的解决方案
这是我想到的两种方法。
在这两种情况下,我都会将锻炼历史存储为日期表。如果有该日期的条目,则表示用户在该日期进行了锻炼。 有趣的是目标存储。
方法 1
每周存储目标(它是 SQLite,因此日期存储为字符串 - 所有日期都只是 'YEAR-MONTH-DAY'):
CREATE TABLE goals (
start_date TEXT,
exercise_days TEXT);
“start_date”是一周的第一天, “exercise_days”是一个以逗号分隔的工作日列表(比如数字 1-7)。
所以对于上面的例子,我们可能有两行:
'2019-08-05', '1,4'
'2019-09-09', '1,3,5'
表示自 2019 年 8 月 5 日起,目标为周一、周四,直到 2019 年 9 月 9 日,目标为周一、周三、周五。所以数据有差距。我不想在 2019-08-12、2019-08-19、2019-08-26 开始的几周内生成数据。
通过这种方法,可以轻松地每周处理数据。当前目标是MAX('start_date')。给定日期的一周目标是MAX('start_date') WHERE 'start_date' <= :date。
但是,当我想获取过去 3 个月的数据并向用户显示他们的进度时,它会变得很麻烦。 或者,也许我想向用户展示实际锻炼天数与他们设定的一年目标的百分比。 在这种情况下,似乎最好的方法是单独获取数据并将其合并到应用程序中(或者可能编写一些复杂的查询),逐周处理。这在性能方面还可以,因为数据量很少,而且我很少需要超过几周的时间。
方法2
以这样的方式存储目标,使每个目标日都是一个记录:
CREATE TABLE goals (
day TEXT,
);
“day”是用户应该锻炼的日子。因此,从 2019 年 9 月 9 日(周一、周三、周五)开始的那一周,我们将:
'2019-09-09'
'2019-09-11'
'2019-09-13'
从 2019 年 8 月 5 日(周一、周四)开始的那一周,我们将:
'2019-08-05'
'2019-08-09'
但是中间的几周呢?
如果我的应用程序可以填满其间的所有星期,那么将这些数据与锻炼历史记录合并并显示用户应该锻炼的天数以及他们实际锻炼的时间会很容易。提取任何给定一周的目标也很容易。
问题是:即使用户没有调整目标,这也要求应用生成“间隔”周的数据。这可以实现为每次应用进程启动时运行的事务。在某些情况下,偶尔使用该应用的用户可能需要相当长的时间(想一想进度条)。
在进行SELECT 查询时,是否有一种巧妙的方法可以生成中间数据?
我不喜欢它需要生成数据的事实。我确实喜欢这样一个事实,即我可以加入表格然后处理它(例如计算应该在八月份有多少锻炼天以及用户实际锻炼了多少天,然后向他们显示百分比,例如“你做了 85%你的目标”——事实上我可以在不加入表格的情况下做到这一点)。
此外,这种方法似乎为我将来的分析提供了更大的灵活性。
但是还有第三种方法吗?或者,也许我想多了? :)
(我主要是询问组织数据的方式,不需要精确的 SQL 查询)
【问题讨论】:
标签: sql sqlite date time-series