我需要按日期范围在多列中求和。每个日期范围是一个月的一个星期。如果是月初或月末,则可以少于7天。 例如,我有2月的日期:
my_user my_date my_value
A 01.02.2019 100
A 02.02.2019 150
B 01.02.2019 90
Z 28.02.2019 120
如何使用如下所示的日期范围格式?
my_user 01/02-03/02 04/02-10/02 11/02-17/02 18/02-24/02 25/02-28/02
A 250 0 0 0 0
B 90 0 0 0 0
Z 0 0 0 0 120
有什么建议吗?谢谢!
答案 0 :(得分:0)
您可以这样做:
select *
from (
select to_char(dt, 'iw') - to_char(trunc(dt, 'month'), 'iw') + 1 wk, usr, val from t)
pivot (sum(val) for wk in (1, 2, 3, 4, 5, 6))
USR 1 2 3 4 5 6
--- ---------- ---------- ---------- ---------- ---------- ----------
A 250
B 90
Z 120
标题编号是一个月中的星期。如果一个月的开始时间是周末,并且超过28天,则最大值可能是6。
您可以根据需要以相似的方式找到每周的第一天和最后一天,但是您不能将它们作为标题,或者至少不那么容易。
编辑:
可以使用数据透视表定义特定的日期范围,只需两个 日期?例如,我需要将2018年12月5日至4日的值求和 2019年1月,2019年1月5日至2019年2月4日,2019年3月5日至4日 2019年4月
是的。一切都取决于我们如何计算第一周和下周。在这里:
to_char(dt, 'iw') - to_char(trunc(dt, 'month'), 'iw') + 1
我要减去给定日期的年份中的星期和该日期的月份中第一天的年份中的星期。您可以简单地用开始日期替换第二个值,方法是在查询中对其进行硬编码,或者通过发送参数进行查询或在子查询中首先找到最短日期:
(to_char(dt, 'iw') - to_char(date '2019-03-05', 'iw')) + 1
或
(to_char(dt, 'iw') - to_char((select min(dt) from data), 'iw')) + 1
编辑2:
但是有一个问题。用户定义的期限包含两年或更长时间。 to_date(..., 'iw')
可以正常工作一年,但是对于两年,我们得到的值分别为51、52、01、02 ...我们必须以某种方式处理此问题,例如:
with t(dt1, dt2) as (select date '2018-12-16', date '2019-01-15' from dual)
select min(dt) mnd, max(dt) mxd, iw, row_number() over (order by min(dt)) rn
from (select dt1 + level - 1 dt, to_char(dt1 + level - 1, 'iw') iw
from t connect by level -1 <= dt2 - dt1)
group by iw
这给了我们
MND MXD IW RN
----------- ----------- -- ----------
2018-12-16 2018-12-16 50 1
2018-12-17 2018-12-23 51 2
2018-12-24 2018-12-30 52 3
2018-12-31 2019-01-06 01 4
2019-01-07 2019-01-13 02 5
2019-01-14 2019-01-15 03 6
第一行中有用户定义的日期范围。然后,我进行了分层查询,遍历了范围分配week
中的所有日期,然后按本周进行分组,找到了每周的开始日期和结束日期以及分配的行号rn
,这些数据可以被数据透视表进一步使用。 / p>
您现在可以简单地将输入数据与此查询结合起来,我们将其命名为weeks
:
from data join weeks on dt between mnd and mxd
并进行枢纽。但是对于更长的时间,您必须找出可以容纳几周的时间,并在数据透视子句in (1, 2, 3, 4...)
中进行指定。您还可以根据需要添加别名:
pivot ... for rn in (1 week01, 2 week02... 12 week12)
没有简单的方法可以避免手动列出它们。如果需要,请在SO中查找oracle dynamic pivot
,那里已经有数百个类似的问题。 ;-)