我想知道除了使用date_trunc使用默认选项之外是否可以截断日期.例如,如果我有一个看起来像这样的表
date dollars
2016-10-03 1
2016-10-05 1
2016-10-10 1
2016-10-17 2
2016-10-24 2
Run Code Online (Sandbox Code Playgroud)
并说我想在每个"双周"期间截断和分组(所以在这个例子中,两个时间段,一个从2016-10-03开始,另一个从2016-10-17开始).
我希望结果如此
date dollars
2016-10-03 3
2016-10-17 4
Run Code Online (Sandbox Code Playgroud)
我怎样才能做到这一点?我知道,如果我想每两周做一次,date_trunc我可以做些什么date_trunc('week', date)呢?或者如果我想使用其他一些自定义日期范围怎么办?
我相信,仅使用一个内置函数就无法做到这一点。但是,有多种方法可以将它们结合使用。
要输出相同的结果,您可以使用以下查询:
SELECT TO_DATE(
CONCAT(
DATE_PART('YEAR', date),
(DATE_PART('WEEK', date)::INTEGER / 2) * 2),
'iyyyiw') AS "date",
SUM(dollars) AS dollars
FROM my_table
GROUP BY 1
ORDER BY 1
Run Code Online (Sandbox Code Playgroud)
让我解释。DATE_PART将从您的日期列中提取星期数(日期从2016-10-03到2016-10-09的值将为40,日期从2016-10-10到2016-10-16的值将具有41,等等。INTEGER将其2强制转换为然后除以将强制进行整数除法,将值截断(20将保持为20,20.5将截断为20等)。保留这个截断的数字是没有用的,因此我将其乘以2以返回要分组的星期数。
我DATE_PART再次使用从您的date列中检索年份,然后使用CONCAT函数将年份和星期数字连接起来,最后使用该TO_DATE函数将包含年份和星期数字的字符串转换为日期格式(使用ISO标准)。
使用此新列将根据需要对数据进行分组。
不过,上述解决方案只能按预期工作,因为您的数据是从指定的日期开始的,该日期2016-10-03的周数为40。让我工作另一个解决方案,该解决方案可以更好地推广到其他日期范围。
假设您希望不按起始的两周分组,2016-10-03而是按起始的前两周分组2016-09-26(前一周)。您可以使用与上述相同的解决方案,但必须稍加修改。
SELECT TO_DATE(
CONCAT(
DATE_PART('YEAR', date),
((DATE_PART('WEEK', date) + 1)::INTEGER / 2) * 2 - 1),
'iyyyiw') AS "date",
SUM(dollars) AS dollars
FROM my_table
GROUP BY 1
ORDER BY 1
Run Code Online (Sandbox Code Playgroud)
在提取星期时+1使用该函数后添加一个权限DATE_PART,将把所有星期“移动”到下一个“ bin”(星期40移动到41,星期41移动到42,等等)。当然,您必须随后将其拿走+1以返回“原始”纸槽。但是,这将导致除法2开始以不同的方式截断所有内容,并且您的查询现在将开始按照从开始的两周对数据进行分组2016-09-26。
回答你的问题
或者,如果我想使用其他自定义日期范围怎么办?
上面的解决方案可以很好地推广到其他情况,例如按三周,两个月分组等。
要开始按其他单位(天,周,月等)进行分组,只需将DATE_PART('WEEK',...)函数DATE_PART('MONTH',...)更改为,并将参数更改iyyyiw为iyyyim(在文档中进行了描述)。您可以使用相同的技巧,使用+1和-1从1月或2月开始对两个月进行分组。
如果通过三星期希望集团,例如,你必须改变数字除以和乘以2来3。在这里,如果你想通过向第一三周内改变在其上组,则需要使用添加的同样的伎俩+1和-1,但你现在可能需要使用+2和-2。
| 归档时间: |
|
| 查看次数: |
418 次 |
| 最近记录: |