我有一个记录跑步记录的表,它有以下几列:
| ID|距离|运行时间|运行日期|
| --|--|--|--|
| 1 | 10 |时间01:35:00| 2023-12-10|
| 2 | 10 |时间01:48:00| 2023-12-16 2023-12-16|
| 3 | 10 |时间01:25:00| 2023-12-17 2023-12-17|
| 4 | 10 |时间01:41:00| 2023-12-23 - 2023 - 2022|
我想计算当前一周和前一周的平均每英里配速(格式为mm:ss)。下面是计算一周平均配速的查询:
select to_char(sum(run_time) / sum(distance), 'mi:ss')
from runs
where run_date between run_date1 and run_date2;
字符串
有没有一种方法可以只用一个查询就做到这一点,并保证结果的第一行对应于第一周(第二行对应于第二周,依此类推)?
这是我能想到的最好的:
select to_char(sum(run_time) / sum(distance), 'mi:ss')
from runs
where run_date between run_date1 and run_date2 union
select to_char(sum(run_time) / sum(distance), 'mi:ss')
from runs
where run_date between run_date3 and run_date4
型
有没有更简洁的方法来写这个?如果我想计算接下来的4周怎么办?我们可以使用in运算符来简化它吗?
4条答案
按热度按时间kxkpmulp1#
generate_series
function让您的问题变得简单:在下面的示例中,100天前到未来100天之间的所有记录将按周分组,星期一是一周的第一天。
如果您想硬编码一个日期范围,只需将
generate_series
中的参数替换为timestamp
s(或转换为timestamp
的日期)。字符串
您也可以不根据Monday-Sunday逻辑对记录进行分组,而是使用
runs
表所包含的内容。型
附加说明:
首先,如果你没有注意到,我会在一周的每个上限上减去1。这是因为
BETWEEN
包括下限和上限。所以对于BETWEEN
,在一周的最后一天发生的运行也会被认为是在下周的第一天发生的。你可以从相同的结果中使用
run_date >= from_date and run_date < to_date
来代替run_date BETWEEN from_date and to_date - 1
。此外,查询计算
W
的部分只是在这里获取generate_series
返回的连续日期中的2个。有一种稍微更紧凑的方式来表达同样的想法:型
然而,我觉得这不太方便:如果你想改变分组,例如从1到2周,你必须确保在查询的3个地方(在
SELECT
,子查询和ON
内部)而不是一个地方。c9qzyr3d2#
使用以下查询计算平均每英里配速:
字符串
此查询返回本周、上周和未来4周的平均每英里配速。根据需要调整间隔。
jyztefdp3#
参见递归构造日历表的例子。同样,你可以使用generate_series代替递归。我引用了递归的使用,以使解决方法完整。
需要设置报告的
end date
和报告数据集包含的number of weeks
。它们可以是请求参数。
字符串
计算
型
需要在first_date附近度过整整一周。
例如,如果end_date的day_of_week(DOW)为星期三(date_part('ISODOW',endDate)=3)
所以
date_add(endDate,(-weeks)的day_of_week|| 'week')::interval)
也是星期三,
我们在first_date上加上(8-3)=5天,所以first_date的day_of_week
always is monday
。有3+(8-3)=3+5=8->8-8/7*7=1。所以,前几周是整周,最后一周是一周。
date_part函数需要使用
ISOYEAR
键。当一周的开始与一年的开始不一致时,这很重要。另请参阅@atmo的评论如果你不需要花整整一周的时间,这可以简化。
测试数据的
型
要求7周的结果是
| 年|weeknum|每英里平均速度|从DT|到dt|周数量|周距|周运行时间|
| --|--|--|--|--|--|--|--|
| 2023 | 48 |null| 2023-11-27 2023-11-27 2023-11-27| 2023-12-03 - 2023 -03 - 01| 0 |null| null|
| 2023 | 49 |时间00:09:30| 2023-12-04 2023-12-04 2023-12-04| 2023-12-10| 1 | 10 |时间01:35:00|
| 2023 | 50 |时间00:09:39| 2023-12-11 - 02 - 02 - 2023-12-11 - 02 - 02| 2023-12-17 2023-12-17| 2 | 20 |三点十三分|
| 2023 | 51 |时间00:08:44| 2023-12-18 2023-12-18| 2023-12-24 - 2023 - 2024 - 2025| 2 | 30 |四点二十二分|
| 2023 | 52 |时间00:08:04| 2023-12-25 - 2023-12-25| 2023-12-31 - 2023| 1 | 15 |02:01:00|
| 2024 | 1 |时间00:08:40| 2024-01-01 2024-01-01| 2024-01-07 2024-01-07| 1 | 15 |两点十分|
| 2024 | 2 |null| 2024-01-08 2024-01-08| 2024-01-14 2024-01-14 2024-01-14| 0 |null| null|
klh5stk14#
你可以使用带有@符号的变量并调用它。Getdate()获取你的系统日期,它可以被修改。作为你的数据结构没有时间作为日期的一部分,你可以使用CAST()来改变它的数据类型。
字符串